@bunnyapp/components 1.6.0 → 1.7.0-beta.2
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 +1204 -904
- 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 +1206 -906
- 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.1';
|
|
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,
|
|
@@ -19840,7 +19850,7 @@ 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$
|
|
19853
|
+
const { Text: Text$z } = antd.Typography;
|
|
19844
19854
|
const handleAllErrorFormats = common.useAllErrorFormats();
|
|
19845
19855
|
const TEST_CARD = '4242424242424242';
|
|
19846
19856
|
const DemoPayForm = () => {
|
|
@@ -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
|
|
|
@@ -20768,14 +20780,14 @@ const AcceptQuoteModal = ({ acceptBoxVisible, formattedQuote, sendAccept, setAcc
|
|
|
20768
20780
|
}, 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
20781
|
};
|
|
20770
20782
|
|
|
20771
|
-
const { Title: Title$2, Text: Text$
|
|
20783
|
+
const { Title: Title$2, Text: Text$x } = antd.Typography;
|
|
20772
20784
|
const showSuccessNotification$2 = common.useSuccessNotification();
|
|
20773
20785
|
const PaymentHoldModal = ({ visible, setVisible, quote, }) => {
|
|
20774
20786
|
const queryClient = reactQuery.useQueryClient();
|
|
20775
20787
|
const token = useToken();
|
|
20776
20788
|
return (jsxRuntime.jsxs(StyledModal$2, { centered: true, onCancel: () => {
|
|
20777
20789
|
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$
|
|
20790
|
+
}, 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
20791
|
amount: quote.amount,
|
|
20780
20792
|
currencyId: quote.currency,
|
|
20781
20793
|
id: quote.quote.id,
|
|
@@ -20825,7 +20837,7 @@ const StyledModal$2 = (props) => {
|
|
|
20825
20837
|
return jsxRuntime.jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
20826
20838
|
};
|
|
20827
20839
|
|
|
20828
|
-
const { Text: Text$
|
|
20840
|
+
const { Text: Text$w } = antd.Typography;
|
|
20829
20841
|
defaultStyled.div `
|
|
20830
20842
|
Text {
|
|
20831
20843
|
width: 100%;
|
|
@@ -20917,7 +20929,7 @@ function QuoteButtons({ isAccepted, formattedQuote, isMobile, hideDownloadButton
|
|
|
20917
20929
|
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
20918
20930
|
return (jsxRuntime.jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
20919
20931
|
color: secondaryColor,
|
|
20920
|
-
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$
|
|
20932
|
+
}, 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
20933
|
? 'Quote is expired'
|
|
20922
20934
|
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
20923
20935
|
? 'Start signing'
|
|
@@ -21038,9 +21050,9 @@ const getColor = (state) => {
|
|
|
21038
21050
|
}
|
|
21039
21051
|
};
|
|
21040
21052
|
|
|
21041
|
-
const { Text: Text$
|
|
21053
|
+
const { Text: Text$v } = antd.Typography;
|
|
21042
21054
|
const TransactionDate = ({ date }) => {
|
|
21043
|
-
return jsxRuntime.jsx(Text$
|
|
21055
|
+
return jsxRuntime.jsx(Text$v, { className: "bunny-text-sm", children: common.formatDate(date) });
|
|
21044
21056
|
};
|
|
21045
21057
|
|
|
21046
21058
|
const ArrowDownToLine = ({ className, color = common.SLATE_600, }) => {
|
|
@@ -21084,13 +21096,13 @@ const TransactionGridCell = defaultStyled.div.withConfig({
|
|
|
21084
21096
|
min-width: 48px;
|
|
21085
21097
|
`;
|
|
21086
21098
|
|
|
21087
|
-
const { Text: Text$
|
|
21099
|
+
const { Text: Text$u } = antd.Typography;
|
|
21088
21100
|
const TransactionsEmptyState = () => {
|
|
21089
21101
|
const { noTransactionsMessage } = react.useContext(TransactionsListContext);
|
|
21090
|
-
return (jsxRuntime.jsx(Text$
|
|
21102
|
+
return (jsxRuntime.jsx(Text$u, { className: "bunny-flex bunny-justify-center bunny-p-4 bunny-text-base", children: noTransactionsMessage || 'There are no transactions' }));
|
|
21091
21103
|
};
|
|
21092
21104
|
|
|
21093
|
-
const { Text: Text$
|
|
21105
|
+
const { Text: Text$t } = antd.Typography;
|
|
21094
21106
|
const isInvoice = (transaction) => {
|
|
21095
21107
|
return transaction.kind === 'INVOICE';
|
|
21096
21108
|
};
|
|
@@ -21098,7 +21110,7 @@ const TransactionRowTitle = ({ transaction }) => {
|
|
|
21098
21110
|
if (!isInvoice(transaction)) {
|
|
21099
21111
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
21100
21112
|
}
|
|
21101
|
-
return (jsxRuntime.jsx(Text$
|
|
21113
|
+
return (jsxRuntime.jsx(Text$t, { className: "bunny-text-slate-400", style: { fontSize: '11px' }, children: transaction.transactionable.number }));
|
|
21102
21114
|
};
|
|
21103
21115
|
|
|
21104
21116
|
function transactionDateToDisplay(transaction, transactionDateType) {
|
|
@@ -21116,7 +21128,7 @@ function transactionDateToDisplay(transaction, transactionDateType) {
|
|
|
21116
21128
|
}
|
|
21117
21129
|
}
|
|
21118
21130
|
|
|
21119
|
-
const { Text: Text$
|
|
21131
|
+
const { Text: Text$s } = antd.Typography;
|
|
21120
21132
|
const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
21121
21133
|
const { columns, transactionDateType } = react.useContext(TransactionsListContext);
|
|
21122
21134
|
const { apiHost, darkMode } = react.useContext(BunnyContext);
|
|
@@ -21144,11 +21156,11 @@ const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
|
21144
21156
|
!showState &&
|
|
21145
21157
|
!showAmount &&
|
|
21146
21158
|
!showDownload &&
|
|
21147
|
-
!showAccountName && (jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsx(Text$
|
|
21159
|
+
!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
21160
|
}) }));
|
|
21149
21161
|
};
|
|
21150
21162
|
|
|
21151
|
-
const { Text: Text$
|
|
21163
|
+
const { Text: Text$r } = antd.Typography;
|
|
21152
21164
|
const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
21153
21165
|
const { columns, transactionDateType } = react.useContext(TransactionsListContext);
|
|
21154
21166
|
const { apiHost, darkMode } = react.useContext(BunnyContext);
|
|
@@ -21170,11 +21182,11 @@ const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
|
21170
21182
|
backgroundColor: index % 2 === 0
|
|
21171
21183
|
? `var(--row-background${darkMode ? '-dark' : ''})`
|
|
21172
21184
|
: `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$
|
|
21185
|
+
}, 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
21186
|
}) }));
|
|
21175
21187
|
};
|
|
21176
21188
|
|
|
21177
|
-
const { Text: Text$
|
|
21189
|
+
const { Text: Text$q } = antd.Typography;
|
|
21178
21190
|
const DISPLAY_WIDTH = 1200;
|
|
21179
21191
|
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
21192
|
common.TransactionKind.INVOICE,
|
|
@@ -21278,7 +21290,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
|
|
|
21278
21290
|
onTransactionDisplayClose === null || onTransactionDisplayClose === void 0 ? void 0 : onTransactionDisplayClose(selectedTransaction);
|
|
21279
21291
|
setDrawerOpen(false);
|
|
21280
21292
|
}
|
|
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$
|
|
21293
|
+
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
21294
|
), showSearchBar && (jsxRuntime.jsx("div", { className: `${isMobile ? 'bunny-w-full' : ''}`, children: jsxRuntime.jsx(antd.Input, { className: searchBarClassName ? searchBarClassName : '', onChange: e => {
|
|
21283
21295
|
const value = e.target.value;
|
|
21284
21296
|
// Allow empty string, numbers, and decimal point
|
|
@@ -21401,7 +21413,7 @@ const useHasTaxPlugin = ({ apiHost, token, }) => {
|
|
|
21401
21413
|
return Boolean(plugins === null || plugins === void 0 ? void 0 : plugins.some((plugin) => plugin.type === "taxation"));
|
|
21402
21414
|
};
|
|
21403
21415
|
|
|
21404
|
-
const MUTATION$
|
|
21416
|
+
const MUTATION$6 = () => `
|
|
21405
21417
|
mutation AccountSignup (
|
|
21406
21418
|
$pluginId: String!,
|
|
21407
21419
|
$paymentMethodId: String,
|
|
@@ -21475,7 +21487,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21475
21487
|
priceListCode,
|
|
21476
21488
|
};
|
|
21477
21489
|
const response = await gqlRequest({
|
|
21478
|
-
query: MUTATION$
|
|
21490
|
+
query: MUTATION$6(),
|
|
21479
21491
|
token,
|
|
21480
21492
|
vars,
|
|
21481
21493
|
apiHost,
|
|
@@ -21486,7 +21498,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21486
21498
|
return response === null || response === void 0 ? void 0 : response.accountSignup;
|
|
21487
21499
|
};
|
|
21488
21500
|
|
|
21489
|
-
const MUTATION$
|
|
21501
|
+
const MUTATION$5 = () => `
|
|
21490
21502
|
mutation QuoteAccountSignup (
|
|
21491
21503
|
$accountName: String!,
|
|
21492
21504
|
$billingContact: ContactAttributes!,
|
|
@@ -21563,7 +21575,7 @@ const quoteAccountSignup = async ({ token, apiHost, priceListCode, accountName,
|
|
|
21563
21575
|
billingDetails,
|
|
21564
21576
|
};
|
|
21565
21577
|
const response = await gqlRequest({
|
|
21566
|
-
query: MUTATION$
|
|
21578
|
+
query: MUTATION$5(),
|
|
21567
21579
|
token,
|
|
21568
21580
|
vars,
|
|
21569
21581
|
apiHost,
|
|
@@ -21641,7 +21653,7 @@ const QUOTE_RECALCULATE_TAXES = `
|
|
|
21641
21653
|
}
|
|
21642
21654
|
}
|
|
21643
21655
|
`;
|
|
21644
|
-
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
21656
|
+
const quoteRecalculateTaxes$2 = async ({ quoteId, apiHost, token, }) => {
|
|
21645
21657
|
var _a, _b;
|
|
21646
21658
|
const vars = { id: quoteId };
|
|
21647
21659
|
const response = await gqlRequest({
|
|
@@ -21656,7 +21668,7 @@ const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
|
21656
21668
|
return (_b = response.quoteRecalculateTaxes) === null || _b === void 0 ? void 0 : _b.quote;
|
|
21657
21669
|
};
|
|
21658
21670
|
|
|
21659
|
-
const MUTATION$
|
|
21671
|
+
const MUTATION$4 = () => `
|
|
21660
21672
|
query PriceList($code: String!) {
|
|
21661
21673
|
priceList (code: $code) {
|
|
21662
21674
|
basePrice
|
|
@@ -21681,7 +21693,7 @@ query PriceList($code: String!) {
|
|
|
21681
21693
|
}`;
|
|
21682
21694
|
const getPriceList = async ({ token, code, apiHost, }) => {
|
|
21683
21695
|
const response = await gqlRequest({
|
|
21684
|
-
query: MUTATION$
|
|
21696
|
+
query: MUTATION$4(),
|
|
21685
21697
|
token,
|
|
21686
21698
|
vars: { code },
|
|
21687
21699
|
apiHost,
|
|
@@ -21691,16 +21703,60 @@ const getPriceList = async ({ token, code, apiHost, }) => {
|
|
|
21691
21703
|
|
|
21692
21704
|
const SubscriptionsContext = react.createContext({});
|
|
21693
21705
|
|
|
21706
|
+
const QuoteContext = react.createContext({});
|
|
21707
|
+
|
|
21694
21708
|
const graphql = initGraphQLTada();
|
|
21695
21709
|
|
|
21696
|
-
|
|
21697
|
-
if (
|
|
21698
|
-
return
|
|
21699
|
-
if (
|
|
21700
|
-
return
|
|
21701
|
-
if (
|
|
21702
|
-
return
|
|
21703
|
-
|
|
21710
|
+
const periodMonthsConverter = (period) => {
|
|
21711
|
+
if (period === 0)
|
|
21712
|
+
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
21713
|
+
else if (period === 1)
|
|
21714
|
+
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
21715
|
+
else if (period === 3)
|
|
21716
|
+
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
21717
|
+
else if (period === 6)
|
|
21718
|
+
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
21719
|
+
else if (period === 12)
|
|
21720
|
+
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
21721
|
+
else
|
|
21722
|
+
return null;
|
|
21723
|
+
};
|
|
21724
|
+
const billingPeriodConverter = (period) => {
|
|
21725
|
+
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
21726
|
+
return 0;
|
|
21727
|
+
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
21728
|
+
return 1;
|
|
21729
|
+
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
21730
|
+
return 3;
|
|
21731
|
+
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
21732
|
+
return 6;
|
|
21733
|
+
else
|
|
21734
|
+
return 12;
|
|
21735
|
+
};
|
|
21736
|
+
|
|
21737
|
+
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
21738
|
+
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
21739
|
+
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
21740
|
+
}
|
|
21741
|
+
|
|
21742
|
+
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
21743
|
+
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
21744
|
+
priceLists {
|
|
21745
|
+
id
|
|
21746
|
+
isVisible
|
|
21747
|
+
periodMonths
|
|
21748
|
+
}
|
|
21749
|
+
}
|
|
21750
|
+
`);
|
|
21751
|
+
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
21752
|
+
// Read fragments
|
|
21753
|
+
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
21754
|
+
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
21755
|
+
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
21756
|
+
var _a;
|
|
21757
|
+
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));
|
|
21758
|
+
});
|
|
21759
|
+
return unpurchasedAddonPriceLists.length > 0;
|
|
21704
21760
|
}
|
|
21705
21761
|
|
|
21706
21762
|
function hasUnpurchasedFeatureAddons(priceList, currentSubscription) {
|
|
@@ -21727,110 +21783,317 @@ function featureAddonSwitchTestId(addonName) {
|
|
|
21727
21783
|
return `feature-addon-switch-${name}`;
|
|
21728
21784
|
}
|
|
21729
21785
|
|
|
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;
|
|
21786
|
+
const canSubscriptionUpgradeFromTrial = (subscription) => {
|
|
21787
|
+
var _a;
|
|
21788
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
21789
|
+
subscription.plan.selfServiceBuy) ||
|
|
21790
|
+
false;
|
|
21745
21791
|
};
|
|
21746
|
-
|
|
21747
|
-
|
|
21748
|
-
return (
|
|
21792
|
+
const canSubscriptionUpgradeFromTrialExpired = (subscription) => {
|
|
21793
|
+
var _a;
|
|
21794
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
21795
|
+
subscription.plan.selfServiceBuy) ||
|
|
21796
|
+
false;
|
|
21749
21797
|
};
|
|
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, {})] }));
|
|
21798
|
+
const isSubscriptionNotActive = (subscription) => {
|
|
21799
|
+
var _a, _b, _c;
|
|
21800
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
21801
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
21802
|
+
((_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
21758
21803
|
};
|
|
21759
|
-
const
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21804
|
+
const isSubscriptionActiveOrPending = (subscription) => {
|
|
21805
|
+
var _a, _b;
|
|
21806
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'ACTIVE') ||
|
|
21807
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'PENDING');
|
|
21763
21808
|
};
|
|
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, }) => {
|
|
21809
|
+
const isSubscriptionTrial = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL'); };
|
|
21810
|
+
const isSubscriptionTrialExpired = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED'); };
|
|
21811
|
+
// Helper function to check if charge is a discount
|
|
21812
|
+
const isDiscount$1 = (kind) => kind === common.QuoteChangeKind.DISCOUNT || kind === common.QuoteChangeKind.FREE_PERIOD_DISCOUNT;
|
|
21813
|
+
const hasPriceTiers = (charge) => {
|
|
21791
21814
|
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;
|
|
21815
|
+
return Boolean((_a = charge === null || charge === void 0 ? void 0 : charge.priceTiers) === null || _a === void 0 ? void 0 : _a.length);
|
|
21803
21816
|
};
|
|
21804
21817
|
|
|
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;
|
|
21818
|
+
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
21819
|
+
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
21820
|
+
const createPlanDescription = (planDescription) => {
|
|
21821
|
+
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
21824
21822
|
};
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
|
|
21829
|
-
|
|
21823
|
+
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
21824
|
+
if (!priceList) {
|
|
21825
|
+
return;
|
|
21826
|
+
}
|
|
21827
|
+
// If a period option is selected, return the charge that matches the selected period option
|
|
21828
|
+
let activeBillingPLCharge;
|
|
21829
|
+
// Default to first price list charge
|
|
21830
|
+
let lowestPLCharge;
|
|
21831
|
+
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
21832
|
+
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
21833
|
+
activeBillingPLCharge = priceList.charges[0];
|
|
21834
|
+
}
|
|
21835
|
+
for (let j = 0; j < priceList.charges.length; j++) {
|
|
21836
|
+
const charge = priceList.charges[j];
|
|
21837
|
+
if (charge.chargeType === common.ChargeType.USAGE || charge.featureAddon === true)
|
|
21838
|
+
continue;
|
|
21839
|
+
if (activeBillingPLCharge) {
|
|
21840
|
+
// If we already found a charge with the same billing period check if this charge is lower
|
|
21841
|
+
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
21842
|
+
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
21843
|
+
activeBillingPLCharge = charge;
|
|
21844
|
+
}
|
|
21845
|
+
}
|
|
21846
|
+
// If a period option is selected, only return the charge if it matches the selected period option
|
|
21847
|
+
else if (selectedPriceList &&
|
|
21848
|
+
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
21849
|
+
activeBillingPLCharge = charge;
|
|
21850
|
+
}
|
|
21851
|
+
// Otherwise, return the lowest price list charge
|
|
21852
|
+
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
21853
|
+
lowestPLCharge = charge;
|
|
21830
21854
|
}
|
|
21831
21855
|
}
|
|
21832
|
-
|
|
21833
|
-
|
|
21856
|
+
return {
|
|
21857
|
+
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
21858
|
+
};
|
|
21859
|
+
};
|
|
21860
|
+
const showErrorNotification$3 = common.useErrorNotification();
|
|
21861
|
+
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
21862
|
+
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
21863
|
+
if (!priceListAddonPlans) {
|
|
21864
|
+
showErrorNotification$3('Price list addon plans are undefined');
|
|
21865
|
+
return false;
|
|
21866
|
+
}
|
|
21867
|
+
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
21868
|
+
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
21869
|
+
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription);
|
|
21870
|
+
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription);
|
|
21871
|
+
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
21872
|
+
// When should priceList be disabled?
|
|
21873
|
+
// if upgradingSubscription?.priceList.id === priceList.id
|
|
21874
|
+
// AND the upgradingSubscription is not in trial
|
|
21875
|
+
// AND cannot purchase feature addons
|
|
21876
|
+
// AND cannot purchase add-on plans
|
|
21877
|
+
// AND selfServiceBuy is false
|
|
21878
|
+
// if upgradingSubscription?.priceList.id != priceList.id
|
|
21879
|
+
// AND upgradingSubscription is expired trial
|
|
21880
|
+
if (isUpgradingSubscriptionPriceList) {
|
|
21881
|
+
return (!existingSubscriptionInTrial &&
|
|
21882
|
+
!existingSubscriptionInTrialExpired &&
|
|
21883
|
+
!canPurchaseFeatureAddons &&
|
|
21884
|
+
!canPurchasePlanAddons);
|
|
21885
|
+
}
|
|
21886
|
+
else {
|
|
21887
|
+
return false;
|
|
21888
|
+
}
|
|
21889
|
+
};
|
|
21890
|
+
|
|
21891
|
+
const CheckoutButton = ({ disabled, onClickCheckout, loading, tooltipText, }) => {
|
|
21892
|
+
const isMobile = common.useIsMobile();
|
|
21893
|
+
const TooltipWrapper = ({ children }) => {
|
|
21894
|
+
if (tooltipText) {
|
|
21895
|
+
return jsxRuntime.jsx(antd.Tooltip, { title: tooltipText, children: children });
|
|
21896
|
+
}
|
|
21897
|
+
return jsxRuntime.jsx("div", { children: children });
|
|
21898
|
+
};
|
|
21899
|
+
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" }) }));
|
|
21900
|
+
};
|
|
21901
|
+
|
|
21902
|
+
var localizedFormat$2 = {exports: {}};
|
|
21903
|
+
|
|
21904
|
+
var localizedFormat$1 = localizedFormat$2.exports;
|
|
21905
|
+
|
|
21906
|
+
var hasRequiredLocalizedFormat;
|
|
21907
|
+
|
|
21908
|
+
function requireLocalizedFormat () {
|
|
21909
|
+
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
21910
|
+
hasRequiredLocalizedFormat = 1;
|
|
21911
|
+
(function (module, exports) {
|
|
21912
|
+
!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)};}}));
|
|
21913
|
+
} (localizedFormat$2));
|
|
21914
|
+
return localizedFormat$2.exports;
|
|
21915
|
+
}
|
|
21916
|
+
|
|
21917
|
+
var localizedFormatExports = requireLocalizedFormat();
|
|
21918
|
+
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
21919
|
+
|
|
21920
|
+
dayjs.extend(localizedFormat);
|
|
21921
|
+
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
21922
|
+
if (value !== 0 && !value)
|
|
21923
|
+
return '';
|
|
21924
|
+
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
21925
|
+
if (isNaN(currencyValue))
|
|
21926
|
+
return value;
|
|
21927
|
+
const localeOptions = {
|
|
21928
|
+
minimumFractionDigits: decimals,
|
|
21929
|
+
maximumFractionDigits: decimals,
|
|
21930
|
+
};
|
|
21931
|
+
localeOptions.style = 'currency';
|
|
21932
|
+
localeOptions.currency = currencyIsoCode;
|
|
21933
|
+
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
21934
|
+
};
|
|
21935
|
+
|
|
21936
|
+
const CheckoutPrice_QuoteFragment = t(`
|
|
21937
|
+
fragment CheckoutPrice_QuoteFragment on Quote {
|
|
21938
|
+
periodAmount
|
|
21939
|
+
amountDue
|
|
21940
|
+
}
|
|
21941
|
+
`);
|
|
21942
|
+
const CheckoutPrice = ({ isUsage, quote: maskedQuote, selectedPriceList, }) => {
|
|
21943
|
+
var _a;
|
|
21944
|
+
// Read fragments
|
|
21945
|
+
const quote = readFragment(CheckoutPrice_QuoteFragment, maskedQuote);
|
|
21946
|
+
// Hooks
|
|
21947
|
+
const isMobile = common.useIsMobile();
|
|
21948
|
+
// amountDue might not be available, so we use periodAmount as a fallback
|
|
21949
|
+
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;
|
|
21950
|
+
if (!isUsage && (!selectedPriceList || displayAmount === undefined))
|
|
21951
|
+
return null;
|
|
21952
|
+
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
21953
|
+
const periodLabel = convertedPeriodMonths ? common.PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
21954
|
+
return (jsxRuntime.jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
21955
|
+
? 'Usage based pricing'
|
|
21956
|
+
: selectedPriceList && displayAmount !== undefined
|
|
21957
|
+
? `${formatCurrency(displayAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, undefined)} / ${periodLabel}`
|
|
21958
|
+
: '' }));
|
|
21959
|
+
};
|
|
21960
|
+
|
|
21961
|
+
const { Text: Text$p } = antd.Typography;
|
|
21962
|
+
const CheckoutBarSummarySection_QuoteFragment = t(`
|
|
21963
|
+
fragment CheckoutBarSummarySection_QuoteFragment on Quote {
|
|
21964
|
+
quoteChanges {
|
|
21965
|
+
charges {
|
|
21966
|
+
id
|
|
21967
|
+
}
|
|
21968
|
+
}
|
|
21969
|
+
...CheckoutPrice_QuoteFragment
|
|
21970
|
+
}
|
|
21971
|
+
`, [CheckoutPrice_QuoteFragment]);
|
|
21972
|
+
const CheckoutBarSummarySection = ({ selectedPriceList, onClickCheckout, }) => {
|
|
21973
|
+
var _a, _b;
|
|
21974
|
+
// Context
|
|
21975
|
+
const { quote: maskedQuote, isQuotePending, isUpdatingQuote } = react.useContext(QuoteContext);
|
|
21976
|
+
const quote = readFragment(CheckoutBarSummarySection_QuoteFragment, maskedQuote);
|
|
21977
|
+
const { isInPreviewMode } = react.useContext(SubscriptionsContext);
|
|
21978
|
+
// Hooks
|
|
21979
|
+
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
21980
|
+
const isMobile = common.useIsMobile();
|
|
21981
|
+
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
21982
|
+
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));
|
|
21983
|
+
const checkoutButtonDisabled = Boolean(!selectedPriceList || !quoteHasCharges || !hasPaymentPlugins || isInPreviewMode);
|
|
21984
|
+
const activeCharge = (_b = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _b === void 0 ? void 0 : _b.activeCharge;
|
|
21985
|
+
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === common.ChargeType.USAGE;
|
|
21986
|
+
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
|
|
21987
|
+
? 'Checkout is disabled in preview mode'
|
|
21988
|
+
: !hasPaymentPlugins
|
|
21989
|
+
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
21990
|
+
: undefined })] }));
|
|
21991
|
+
};
|
|
21992
|
+
|
|
21993
|
+
const MUTATION$3 = `{
|
|
21994
|
+
currentUser {
|
|
21995
|
+
taxationRequiredAccountFields
|
|
21996
|
+
}
|
|
21997
|
+
}`;
|
|
21998
|
+
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
21999
|
+
var _a, _b;
|
|
22000
|
+
const response = await gqlRequest({
|
|
22001
|
+
query: MUTATION$3,
|
|
22002
|
+
token,
|
|
22003
|
+
apiHost: apiHost,
|
|
22004
|
+
});
|
|
22005
|
+
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
|
|
22006
|
+
? response.currentUser.taxationRequiredAccountFields
|
|
22007
|
+
: null;
|
|
22008
|
+
};
|
|
22009
|
+
|
|
22010
|
+
const BunnyFooterIcon = ({ color }) => {
|
|
22011
|
+
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" }) }) })] }));
|
|
22012
|
+
};
|
|
22013
|
+
|
|
22014
|
+
const { Text: Text$o } = antd.Typography;
|
|
22015
|
+
const Footer = ({ className }) => {
|
|
22016
|
+
const token = useToken();
|
|
22017
|
+
const { currentUser } = useCurrentUserData(token);
|
|
22018
|
+
const { privacyUrl, termsUrl } = currentUser;
|
|
22019
|
+
const isMobile = common.useIsMobile();
|
|
22020
|
+
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, {})] }));
|
|
22021
|
+
};
|
|
22022
|
+
const BunnyMarketingLink = () => {
|
|
22023
|
+
const [isHovered, setIsHovered] = react.useState(false);
|
|
22024
|
+
const isMobile = common.useIsMobile();
|
|
22025
|
+
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 }) })] }) }) }));
|
|
22026
|
+
};
|
|
22027
|
+
const StyedLink = styled.a `
|
|
22028
|
+
color: ${common.SLATE_400};
|
|
22029
|
+
transition: color 0.3s;
|
|
22030
|
+
&:hover {
|
|
22031
|
+
color: ${common.SLATE_500};
|
|
22032
|
+
}
|
|
22033
|
+
text-decoration: none;
|
|
22034
|
+
`;
|
|
22035
|
+
const StyledBunnyLink = styled(StyedLink) `
|
|
22036
|
+
&:hover {
|
|
22037
|
+
color: ${common.PRIMARY_COLOR} !important;
|
|
22038
|
+
}
|
|
22039
|
+
`;
|
|
22040
|
+
|
|
22041
|
+
const MUTATION$2 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
22042
|
+
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
22043
|
+
quoteChange {
|
|
22044
|
+
id
|
|
22045
|
+
charges {
|
|
22046
|
+
id
|
|
22047
|
+
amount
|
|
22048
|
+
couponId
|
|
22049
|
+
}
|
|
22050
|
+
}
|
|
22051
|
+
}
|
|
22052
|
+
}`;
|
|
22053
|
+
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22054
|
+
var _a;
|
|
22055
|
+
const vars = { couponCode, quoteChangeId };
|
|
22056
|
+
const response = await gqlRequest({
|
|
22057
|
+
query: MUTATION$2,
|
|
22058
|
+
token,
|
|
22059
|
+
vars,
|
|
22060
|
+
apiHost,
|
|
22061
|
+
});
|
|
22062
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22063
|
+
if (errors)
|
|
22064
|
+
throw errors;
|
|
22065
|
+
return response.quote;
|
|
22066
|
+
};
|
|
22067
|
+
|
|
22068
|
+
const MUTATION$1 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
|
|
22069
|
+
quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
|
|
22070
|
+
errors
|
|
22071
|
+
}
|
|
22072
|
+
}
|
|
22073
|
+
`;
|
|
22074
|
+
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22075
|
+
var _a;
|
|
22076
|
+
const vars = { couponCode, quoteChangeId };
|
|
22077
|
+
const response = await gqlRequest({
|
|
22078
|
+
query: MUTATION$1,
|
|
22079
|
+
token,
|
|
22080
|
+
vars,
|
|
22081
|
+
apiHost,
|
|
22082
|
+
});
|
|
22083
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeRemoveCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22084
|
+
if (errors)
|
|
22085
|
+
throw errors;
|
|
22086
|
+
return response.quote;
|
|
22087
|
+
};
|
|
22088
|
+
|
|
22089
|
+
const COUPONS_QUERY = (filter) => `
|
|
22090
|
+
query Coupons {
|
|
22091
|
+
coupons(filter: ${filter ? `"${filter}"` : 'null'}) {
|
|
22092
|
+
totalCount
|
|
22093
|
+
}
|
|
22094
|
+
}
|
|
22095
|
+
`;
|
|
22096
|
+
const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
21834
22097
|
const response = await gqlRequest({
|
|
21835
22098
|
query: COUPONS_QUERY(filter),
|
|
21836
22099
|
token,
|
|
@@ -21840,7 +22103,7 @@ const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
|
21840
22103
|
return response === null || response === void 0 ? void 0 : response.coupons;
|
|
21841
22104
|
};
|
|
21842
22105
|
|
|
21843
|
-
const showErrorNotification$
|
|
22106
|
+
const showErrorNotification$2 = common.useErrorNotification();
|
|
21844
22107
|
const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCouponRemoved, }) => {
|
|
21845
22108
|
const { data: coupons } = reactQuery.useQuery({
|
|
21846
22109
|
queryKey: ['coupons', token],
|
|
@@ -21866,7 +22129,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
21866
22129
|
},
|
|
21867
22130
|
onError: (error) => {
|
|
21868
22131
|
var _a, _b;
|
|
21869
|
-
showErrorNotification$
|
|
22132
|
+
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');
|
|
21870
22133
|
},
|
|
21871
22134
|
});
|
|
21872
22135
|
const { mutate: removeCoupon, isPending: isRemovingCoupon } = reactQuery.useMutation({
|
|
@@ -21886,7 +22149,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
21886
22149
|
},
|
|
21887
22150
|
onError: (error) => {
|
|
21888
22151
|
var _a, _b;
|
|
21889
|
-
showErrorNotification$
|
|
22152
|
+
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');
|
|
21890
22153
|
},
|
|
21891
22154
|
});
|
|
21892
22155
|
return {
|
|
@@ -21986,7 +22249,7 @@ const QuoteFields_QuoteFragment = t(`
|
|
|
21986
22249
|
}
|
|
21987
22250
|
`);
|
|
21988
22251
|
|
|
21989
|
-
const MUTATION
|
|
22252
|
+
const MUTATION = `
|
|
21990
22253
|
mutation accountUpdate(
|
|
21991
22254
|
$id: ID!,
|
|
21992
22255
|
$attributes: AccountAttributes!) {
|
|
@@ -22007,11 +22270,11 @@ mutation accountUpdate(
|
|
|
22007
22270
|
}
|
|
22008
22271
|
}
|
|
22009
22272
|
`;
|
|
22010
|
-
const accountUpdate = async ({ accountId, attributes, token, apiHost, }) => {
|
|
22273
|
+
const accountUpdate$1 = async ({ accountId, attributes, token, apiHost, }) => {
|
|
22011
22274
|
var _a;
|
|
22012
22275
|
const vars = { id: accountId, attributes };
|
|
22013
22276
|
const response = await gqlRequest({
|
|
22014
|
-
query: MUTATION
|
|
22277
|
+
query: MUTATION,
|
|
22015
22278
|
token,
|
|
22016
22279
|
vars,
|
|
22017
22280
|
apiHost,
|
|
@@ -22032,7 +22295,7 @@ const TaxationForm = ({ account, accountId }) => {
|
|
|
22032
22295
|
// Mutations
|
|
22033
22296
|
const { mutate: updateAccount, isPending: isUpdatingAccount } = reactQuery.useMutation({
|
|
22034
22297
|
mutationFn: async (changedFormData) => {
|
|
22035
|
-
const account = await accountUpdate({
|
|
22298
|
+
const account = await accountUpdate$1({
|
|
22036
22299
|
accountId,
|
|
22037
22300
|
attributes: changedFormData,
|
|
22038
22301
|
token,
|
|
@@ -22058,6 +22321,7 @@ const FormBillingState = () => {
|
|
|
22058
22321
|
return (jsxRuntime.jsx(antd.Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsxRuntime.jsx(antd.Input, { placeholder: "State" }) }));
|
|
22059
22322
|
};
|
|
22060
22323
|
|
|
22324
|
+
const { Text: Text$n } = antd.Typography;
|
|
22061
22325
|
// HACK: I have imported QuoteFields_QuoteFragment here as a hack to ensure I have all of the quote data needed for
|
|
22062
22326
|
// the eventual children of this component.
|
|
22063
22327
|
// Solution: Eventually all children of this component should be using query fragments to avoid this
|
|
@@ -22143,7 +22407,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
22143
22407
|
}
|
|
22144
22408
|
if (taxationRequiredAccountFields)
|
|
22145
22409
|
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsxRuntime.jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
22146
|
-
return (jsxRuntime.jsx(
|
|
22410
|
+
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 &&
|
|
22147
22411
|
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
22412
|
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
22149
22413
|
var _a;
|
|
@@ -22152,7 +22416,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
22152
22416
|
removeCoupon(couponCode);
|
|
22153
22417
|
}
|
|
22154
22418
|
});
|
|
22155
|
-
}, children: "Remove coupon(s)" }))] })) : (jsxRuntime.
|
|
22419
|
+
}, 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" })] })) }));
|
|
22156
22420
|
};
|
|
22157
22421
|
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
22158
22422
|
const isMobile = common.useIsMobile();
|
|
@@ -22163,7 +22427,7 @@ const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
|
22163
22427
|
: {}
|
|
22164
22428
|
: {
|
|
22165
22429
|
width: '100%',
|
|
22166
|
-
maxWidth: '
|
|
22430
|
+
maxWidth: '400px',
|
|
22167
22431
|
}),
|
|
22168
22432
|
}, children: children }));
|
|
22169
22433
|
};
|
|
@@ -22179,7 +22443,7 @@ const Checkout_QuoteFragment = t(`
|
|
|
22179
22443
|
...QuoteCheckout_QuoteFragment
|
|
22180
22444
|
}
|
|
22181
22445
|
`, [QuoteCheckout_QuoteFragment]);
|
|
22182
|
-
const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
22446
|
+
const Checkout = ({ onCancel, onSuccess, onFail, onRecalculateTaxes, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
22183
22447
|
var _a, _b, _c, _d, _e;
|
|
22184
22448
|
const { apiHost } = react.useContext(BunnyContext);
|
|
22185
22449
|
const isMobile = common.useIsMobile();
|
|
@@ -22190,7 +22454,6 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22190
22454
|
apiHost,
|
|
22191
22455
|
token,
|
|
22192
22456
|
});
|
|
22193
|
-
const queryClient = reactQuery.useQueryClient();
|
|
22194
22457
|
// Queries
|
|
22195
22458
|
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = reactQuery.useQuery({
|
|
22196
22459
|
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
@@ -22204,23 +22467,12 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22204
22467
|
common.getAccount({ id: quote.accountId, apiHost, token, componentsVersion: PACKAGE_VERSION }),
|
|
22205
22468
|
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
22206
22469
|
});
|
|
22470
|
+
// Use onRecalculateTaxes callback because parents need to define recalculateTaxes to get and set the right quote data they need
|
|
22207
22471
|
async function recalculateTaxes() {
|
|
22208
22472
|
if (quote) {
|
|
22209
22473
|
if (!quote.id)
|
|
22210
22474
|
throw new Error('Quote ID is required');
|
|
22211
|
-
|
|
22212
|
-
quoteId: quote.id,
|
|
22213
|
-
apiHost,
|
|
22214
|
-
token,
|
|
22215
|
-
});
|
|
22216
|
-
if (updatedQuote) {
|
|
22217
|
-
const quoteKey = queryKeyFactory.createObjectKey({
|
|
22218
|
-
id: updatedQuote.id,
|
|
22219
|
-
objectName: 'editingQuote',
|
|
22220
|
-
token,
|
|
22221
|
-
});
|
|
22222
|
-
queryClient.setQueryData(quoteKey, updatedQuote);
|
|
22223
|
-
}
|
|
22475
|
+
onRecalculateTaxes(quote.id);
|
|
22224
22476
|
}
|
|
22225
22477
|
return {};
|
|
22226
22478
|
}
|
|
@@ -22254,9 +22506,17 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22254
22506
|
} })) : (jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess }))] }), jsxRuntime.jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
22255
22507
|
};
|
|
22256
22508
|
|
|
22257
|
-
|
|
22509
|
+
function canEditChargeQuantity(charge) {
|
|
22510
|
+
if (!charge)
|
|
22511
|
+
return false;
|
|
22512
|
+
if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
|
|
22513
|
+
return false;
|
|
22514
|
+
if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
|
|
22515
|
+
return false;
|
|
22516
|
+
return true;
|
|
22517
|
+
}
|
|
22258
22518
|
|
|
22259
|
-
const { Text: Text$
|
|
22519
|
+
const { Text: Text$m } = antd.Typography;
|
|
22260
22520
|
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
22261
22521
|
var _a;
|
|
22262
22522
|
const [isTooltipOpen, setIsTooltipOpen] = react.useState(false);
|
|
@@ -22269,7 +22529,7 @@ const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChang
|
|
|
22269
22529
|
setIsTooltipOpen(false);
|
|
22270
22530
|
}, 6000);
|
|
22271
22531
|
}, []);
|
|
22272
|
-
return (jsxRuntime.jsxs(Text$
|
|
22532
|
+
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: {
|
|
22273
22533
|
body: {
|
|
22274
22534
|
paddingTop: '0.75rem',
|
|
22275
22535
|
paddingBottom: '0.75rem',
|
|
@@ -22280,222 +22540,7 @@ const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChang
|
|
|
22280
22540
|
};
|
|
22281
22541
|
const QuantityLabel = ({ activeCharge }) => {
|
|
22282
22542
|
const chargeName = activeCharge.name;
|
|
22283
|
-
return (jsxRuntime.jsx(Text$
|
|
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;
|
|
22440
|
-
}
|
|
22441
|
-
};
|
|
22442
|
-
|
|
22443
|
-
const CheckoutButton = ({ checkoutButtonDisabled, onClickCheckout, loading, tooltipText, }) => {
|
|
22444
|
-
const isMobile = common.useIsMobile();
|
|
22445
|
-
const TooltipWrapper = ({ children }) => {
|
|
22446
|
-
if (tooltipText) {
|
|
22447
|
-
return jsxRuntime.jsx(antd.Tooltip, { title: tooltipText, children: children });
|
|
22448
|
-
}
|
|
22449
|
-
return jsxRuntime.jsx("div", { children: children });
|
|
22450
|
-
};
|
|
22451
|
-
return (jsxRuntime.jsx(TooltipWrapper, { children: jsxRuntime.jsx(antd.Button, { className: isMobile ? 'w-full' : '', disabled: checkoutButtonDisabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
22452
|
-
};
|
|
22453
|
-
|
|
22454
|
-
const CheckoutPrice = ({ isUsage, quote, selectedPriceList, }) => {
|
|
22455
|
-
const isMobile = common.useIsMobile();
|
|
22456
|
-
if (!isUsage && (!selectedPriceList || (quote === null || quote === void 0 ? void 0 : quote.periodAmount) === undefined))
|
|
22457
|
-
return null;
|
|
22458
|
-
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
22459
|
-
const periodLabel = convertedPeriodMonths ? common.PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
22460
|
-
return (jsxRuntime.jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
22461
|
-
? 'Usage based pricing'
|
|
22462
|
-
: selectedPriceList && (quote === null || quote === void 0 ? void 0 : quote.periodAmount) !== undefined
|
|
22463
|
-
? `${common.formatCurrency(quote.periodAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, 0)} / ${periodLabel}`
|
|
22464
|
-
: '' }));
|
|
22465
|
-
};
|
|
22466
|
-
|
|
22467
|
-
const { Text: Text$m } = antd.Typography;
|
|
22468
|
-
const CheckoutBarSummarySection = ({ open, selectedPriceList, onClickCheckout, }) => {
|
|
22469
|
-
var _a;
|
|
22470
|
-
// Context
|
|
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();
|
|
22478
|
-
const isMobile = common.useIsMobile();
|
|
22479
|
-
// Derived state
|
|
22480
|
-
const isFetching = queryClient.isFetching({
|
|
22481
|
-
queryKey: common.QueryKeyFactory.default.planChangeOptionsKey({
|
|
22482
|
-
subscriptionId: upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.id,
|
|
22483
|
-
token,
|
|
22484
|
-
}),
|
|
22485
|
-
});
|
|
22486
|
-
// When should checkout button be disabled?
|
|
22487
|
-
const isUpdatingCharges = (quote === null || quote === void 0 ? void 0 : quote.quoteChanges.some(qc => qc.kind === 'UPDATE' && qc.charges.length > 0)) || false;
|
|
22488
|
-
const isUpgradingSubscription = selectedPriceList.id !== (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id);
|
|
22489
|
-
const disableCheckoutButton = Boolean(!selectedPriceList || isFetching || !(isUpgradingSubscription || isUpdatingCharges) || open);
|
|
22490
|
-
const checkoutButtonDisabled = (quote === null || quote === void 0 ? void 0 : quote.amountDue) && (quote === null || quote === void 0 ? void 0 : quote.amountDue) > 0 ? false : disableCheckoutButton;
|
|
22491
|
-
const activeCharge = (_a = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _a === void 0 ? void 0 : _a.activeCharge;
|
|
22492
|
-
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === common.ChargeType.USAGE;
|
|
22493
|
-
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
22494
|
-
return (jsxRuntime.jsxs(Text$m, { 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, { checkoutButtonDisabled: checkoutButtonDisabled || !hasPaymentPlugins || isInPreviewMode, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
22495
|
-
? 'Checkout is disabled in preview mode'
|
|
22496
|
-
: !hasPaymentPlugins
|
|
22497
|
-
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
22498
|
-
: undefined })] }));
|
|
22543
|
+
return (jsxRuntime.jsx(Text$m, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
22499
22544
|
};
|
|
22500
22545
|
|
|
22501
22546
|
const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
@@ -22515,8 +22560,8 @@ const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
|
22515
22560
|
`, [Checkout_QuoteFragment]);
|
|
22516
22561
|
const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onCheckoutSuccess, }) => {
|
|
22517
22562
|
// Context
|
|
22518
|
-
const { shadow
|
|
22519
|
-
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, isFeatureAddonsLoading, isUpdatingQuote, } = react.useContext(QuoteContext);
|
|
22563
|
+
const { shadow } = react.useContext(SubscriptionsContext);
|
|
22564
|
+
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, onRecalculateTaxes, isFeatureAddonsLoading, isUpdatingQuote, } = react.useContext(QuoteContext);
|
|
22520
22565
|
// Read fragments
|
|
22521
22566
|
const quote = readFragment(PlanPickerCheckoutBar_QuoteFragment, maskedQuote);
|
|
22522
22567
|
// Local state
|
|
@@ -22564,9 +22609,6 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22564
22609
|
const isFeatureAddon = charge.featureAddon;
|
|
22565
22610
|
const quantity = getFeatureQuantity((_d = charge.feature) === null || _d === void 0 ? void 0 : _d.id, charge.id);
|
|
22566
22611
|
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
22612
|
if (!quantity)
|
|
22571
22613
|
return null;
|
|
22572
22614
|
// if charge is a feature addon, and a corresponding quote charge is not found in quote, return null
|
|
@@ -22577,9 +22619,40 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22577
22619
|
return (jsxRuntime.jsx(CheckoutBarInput, { disabled: isDisabled, priceListCharge: charge, quantity: quantity, onQuantityChanged: quantity => {
|
|
22578
22620
|
onChangeQuantity(charge.id, quantity);
|
|
22579
22621
|
} }, index));
|
|
22580
|
-
}) }), jsxRuntime.jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true),
|
|
22622
|
+
}) }), 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
22623
|
};
|
|
22582
22624
|
|
|
22625
|
+
const useQuoteUpdateFeatureAddon_QuoteFragment = t(`
|
|
22626
|
+
fragment useQuoteUpdateFeatureAddon_QuoteFragment on Quote {
|
|
22627
|
+
id
|
|
22628
|
+
startDate
|
|
22629
|
+
}
|
|
22630
|
+
`);
|
|
22631
|
+
|
|
22632
|
+
const FeatureAddonRow_QuoteFragment = t(`
|
|
22633
|
+
fragment FeatureAddonRow_QuoteFragment on Quote {
|
|
22634
|
+
...useQuoteUpdateFeatureAddon_QuoteFragment
|
|
22635
|
+
}
|
|
22636
|
+
`, [useQuoteUpdateFeatureAddon_QuoteFragment]);
|
|
22637
|
+
|
|
22638
|
+
const useToggleAddonPlan_QuoteFragment = t(`
|
|
22639
|
+
fragment useToggleAddonPlan_QuoteFragment on Quote {
|
|
22640
|
+
quoteChanges {
|
|
22641
|
+
priceList {
|
|
22642
|
+
id
|
|
22643
|
+
}
|
|
22644
|
+
id
|
|
22645
|
+
}
|
|
22646
|
+
id
|
|
22647
|
+
}
|
|
22648
|
+
`);
|
|
22649
|
+
|
|
22650
|
+
const AddonPlanRow_QuoteFragment = t(`
|
|
22651
|
+
fragment AddonPlanRow_QuoteFragment on Quote {
|
|
22652
|
+
...useToggleAddonPlan_QuoteFragment
|
|
22653
|
+
}
|
|
22654
|
+
`, [useToggleAddonPlan_QuoteFragment]);
|
|
22655
|
+
|
|
22583
22656
|
/**
|
|
22584
22657
|
* Central quote fragment for QuoteProvider context.
|
|
22585
22658
|
*
|
|
@@ -22597,6 +22670,7 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22597
22670
|
id
|
|
22598
22671
|
currencyId
|
|
22599
22672
|
amountDue
|
|
22673
|
+
startDate
|
|
22600
22674
|
quoteChanges {
|
|
22601
22675
|
id
|
|
22602
22676
|
kind
|
|
@@ -22620,75 +22694,17 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22620
22694
|
}
|
|
22621
22695
|
}
|
|
22622
22696
|
...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
|
-
`;
|
|
22697
|
+
...CheckoutBarSummarySection_QuoteFragment
|
|
22698
|
+
...AddonPlanRow_QuoteFragment
|
|
22699
|
+
...FeatureAddonRow_QuoteFragment
|
|
22700
|
+
}
|
|
22701
|
+
`, [
|
|
22702
|
+
PlanPickerCheckoutBar_QuoteFragment,
|
|
22703
|
+
CheckoutBarSummarySection_QuoteFragment,
|
|
22704
|
+
AddonPlanRow_QuoteFragment,
|
|
22705
|
+
FeatureAddonRow_QuoteFragment,
|
|
22706
|
+
]);
|
|
22707
|
+
|
|
22692
22708
|
const FormattedQuoteField_QuoteFragment = t(`
|
|
22693
22709
|
fragment FormattedQuoteField_QuoteFragment on Quote {
|
|
22694
22710
|
formattedQuote {
|
|
@@ -22696,7 +22712,7 @@ const FormattedQuoteField_QuoteFragment = t(`
|
|
|
22696
22712
|
}
|
|
22697
22713
|
}
|
|
22698
22714
|
`);
|
|
22699
|
-
const query$
|
|
22715
|
+
const query$5 = t(`
|
|
22700
22716
|
query quote($id: ID, $removeFormattedQuoteField: Boolean!) {
|
|
22701
22717
|
quote(id: $id) {
|
|
22702
22718
|
...QuoteContext_QuoteFragment
|
|
@@ -22705,7 +22721,7 @@ const query$3 = t(`
|
|
|
22705
22721
|
}
|
|
22706
22722
|
`, [QuoteContext_QuoteFragment, FormattedQuoteField_QuoteFragment]);
|
|
22707
22723
|
const getQuote$1 = async ({ id, token, apiHost, removeFormattedQuoteField = false, }) => {
|
|
22708
|
-
const response = await execute(query$
|
|
22724
|
+
const response = await execute(query$5, { apiHost, token }, { id, removeFormattedQuoteField });
|
|
22709
22725
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
22710
22726
|
};
|
|
22711
22727
|
|
|
@@ -22810,7 +22826,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
22810
22826
|
});
|
|
22811
22827
|
const { mutate: recalculateTaxesMutation } = reactQuery.useMutation({
|
|
22812
22828
|
mutationFn: (quoteId) => {
|
|
22813
|
-
return quoteRecalculateTaxes({ token, apiHost, quoteId });
|
|
22829
|
+
return quoteRecalculateTaxes$2({ token, apiHost, quoteId });
|
|
22814
22830
|
},
|
|
22815
22831
|
onError: (error) => {
|
|
22816
22832
|
if (!error[0].message.includes('Ensure that you have a taxation plugin')) {
|
|
@@ -22991,7 +23007,7 @@ const useQuoteQueryData = (quoteId) => {
|
|
|
22991
23007
|
return data;
|
|
22992
23008
|
};
|
|
22993
23009
|
|
|
22994
|
-
const useSetQuoteQueryData = () => {
|
|
23010
|
+
const useSetQuoteQueryData$1 = () => {
|
|
22995
23011
|
const token = useToken();
|
|
22996
23012
|
const queryClient = reactQuery.useQueryClient();
|
|
22997
23013
|
const setQuoteQueryData = (quoteId, quote) => {
|
|
@@ -23030,6 +23046,9 @@ const QuantityInput_QuoteFragment = t(`
|
|
|
23030
23046
|
}
|
|
23031
23047
|
`, []);
|
|
23032
23048
|
|
|
23049
|
+
const useQuoteIsLoadingState = (isLoading) => react.useState(isLoading !== null && isLoading !== void 0 ? isLoading : false);
|
|
23050
|
+
const [QuoteIsLoadingProvider, useQuoteIsLoading] = createStateContext(useQuoteIsLoadingState);
|
|
23051
|
+
|
|
23033
23052
|
const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
23034
23053
|
fragment QuoteChangeSummarySection_QuoteFragment on Quote {
|
|
23035
23054
|
id
|
|
@@ -23041,10 +23060,11 @@ const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
|
23041
23060
|
const QuoteChangeSummarySection = ({ openCheckout, errorUpdatingQuantity, }) => {
|
|
23042
23061
|
const isMobile = common.useIsMobile();
|
|
23043
23062
|
const [quoteId] = useQuoteId();
|
|
23063
|
+
const [isQuoteLoading] = useQuoteIsLoading();
|
|
23044
23064
|
const maskedQuote = useQuoteQueryData(quoteId);
|
|
23045
23065
|
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" }) })] }));
|
|
23066
|
+
const disabled = !quoteId || !quote || errorUpdatingQuantity || isQuoteLoading;
|
|
23067
|
+
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
23068
|
};
|
|
23049
23069
|
|
|
23050
23070
|
const QuantityDrawer_QuoteFragment = t(`
|
|
@@ -23056,7 +23076,7 @@ const QuantityDrawer_QuoteFragment = t(`
|
|
|
23056
23076
|
}
|
|
23057
23077
|
`, [Checkout_QuoteFragment, QuantityInput_QuoteFragment, QuoteChangeSummarySection_QuoteFragment]);
|
|
23058
23078
|
|
|
23059
|
-
const mutation$
|
|
23079
|
+
const mutation$c = t(`
|
|
23060
23080
|
mutation QuoteChargeCreate(
|
|
23061
23081
|
$quoteChangeId: ID!
|
|
23062
23082
|
$startDate: ISO8601Date!
|
|
@@ -23091,11 +23111,11 @@ const mutation$4 = t(`
|
|
|
23091
23111
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23092
23112
|
const quoteChargeCreate$1 = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
23093
23113
|
var _a;
|
|
23094
|
-
const response = await execute(mutation$
|
|
23114
|
+
const response = await execute(mutation$c, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
23095
23115
|
return (_a = response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
23096
23116
|
};
|
|
23097
23117
|
|
|
23098
|
-
const mutation$
|
|
23118
|
+
const mutation$b = t(`
|
|
23099
23119
|
mutation QuoteChargeUpdate($quoteChargeId: ID!, $quantity: Int) {
|
|
23100
23120
|
quoteChargeUpdate(quoteChargeId: $quoteChargeId, quantity: $quantity) {
|
|
23101
23121
|
quoteCharge {
|
|
@@ -23114,14 +23134,29 @@ const mutation$3 = t(`
|
|
|
23114
23134
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23115
23135
|
const quoteChargeUpdate = async (quoteChargeId, quantity, apiHost, token) => {
|
|
23116
23136
|
var _a, _b;
|
|
23117
|
-
const response = await execute(mutation$
|
|
23137
|
+
const response = await execute(mutation$b, { apiHost, token }, { quoteChargeId, quantity });
|
|
23118
23138
|
if ((_a = response.quoteChargeUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23119
23139
|
throw new Error(response.quoteChargeUpdate.errors[0]);
|
|
23120
23140
|
}
|
|
23121
23141
|
return (_b = response.quoteChargeUpdate) === null || _b === void 0 ? void 0 : _b.quoteCharge;
|
|
23122
23142
|
};
|
|
23123
23143
|
|
|
23124
|
-
const mutation$
|
|
23144
|
+
const mutation$a = t(`
|
|
23145
|
+
mutation QuoteDelete($id: ID!) {
|
|
23146
|
+
quoteDelete(id: $id) {
|
|
23147
|
+
errors
|
|
23148
|
+
quote {
|
|
23149
|
+
id
|
|
23150
|
+
}
|
|
23151
|
+
}
|
|
23152
|
+
}
|
|
23153
|
+
`, []);
|
|
23154
|
+
const quoteDelete = async ({ id, token, apiHost }) => {
|
|
23155
|
+
const response = await execute(mutation$a, { apiHost, token }, { id });
|
|
23156
|
+
return response.quoteDelete;
|
|
23157
|
+
};
|
|
23158
|
+
|
|
23159
|
+
const mutation$9 = t(`
|
|
23125
23160
|
mutation quoteSubscriptionUpdate($subscriptionIds: [ID!]!) {
|
|
23126
23161
|
quoteSubscriptionUpdate(subscriptionIds: $subscriptionIds) {
|
|
23127
23162
|
quote {
|
|
@@ -23150,7 +23185,7 @@ const mutation$2 = t(`
|
|
|
23150
23185
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23151
23186
|
const quoteSubscriptionUpdate = async (subscriptionIds, apiHost, token) => {
|
|
23152
23187
|
var _a, _b;
|
|
23153
|
-
const response = await execute(mutation$
|
|
23188
|
+
const response = await execute(mutation$9, { apiHost, token }, { subscriptionIds });
|
|
23154
23189
|
if ((_a = response.quoteSubscriptionUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23155
23190
|
throw new Error(response.quoteSubscriptionUpdate.errors[0]);
|
|
23156
23191
|
}
|
|
@@ -23219,6 +23254,23 @@ const canShowChangeQuantities = ({ subscriptions, }) => {
|
|
|
23219
23254
|
});
|
|
23220
23255
|
};
|
|
23221
23256
|
|
|
23257
|
+
/**
|
|
23258
|
+
* Note: It is good practice to isolate useEffects into their own components.
|
|
23259
|
+
* This approach helps prevent unnecessary re-renders when data is unchanged,
|
|
23260
|
+
* since useEffect will only be triggered in this dedicated sibling component.
|
|
23261
|
+
*/
|
|
23262
|
+
const QuoteIsLoadingUpdater = ({ quoteIsPending }) => {
|
|
23263
|
+
const [, setQuoteIsLoading] = useQuoteIsLoading();
|
|
23264
|
+
const prevValue = react.useRef(quoteIsPending);
|
|
23265
|
+
react.useEffect(() => {
|
|
23266
|
+
if (prevValue.current !== quoteIsPending) {
|
|
23267
|
+
setQuoteIsLoading(quoteIsPending);
|
|
23268
|
+
prevValue.current = quoteIsPending;
|
|
23269
|
+
}
|
|
23270
|
+
}, [quoteIsPending, setQuoteIsLoading]);
|
|
23271
|
+
return null;
|
|
23272
|
+
};
|
|
23273
|
+
|
|
23222
23274
|
const QuantityInput_SubscriptionChargeFragment = t(`
|
|
23223
23275
|
fragment QuantityInput_SubscriptionChargeFragment on SubscriptionCharge {
|
|
23224
23276
|
id
|
|
@@ -23230,7 +23282,6 @@ const QuantityInput_SubscriptionChargeFragment = t(`
|
|
|
23230
23282
|
const QuantityInput_SubscriptionFragment = t(`
|
|
23231
23283
|
fragment QuantityInput_SubscriptionFragment on Subscription {
|
|
23232
23284
|
id
|
|
23233
|
-
state
|
|
23234
23285
|
priceList {
|
|
23235
23286
|
id
|
|
23236
23287
|
}
|
|
@@ -23246,6 +23297,16 @@ const QuantityInput_SubscriptionFragment = t(`
|
|
|
23246
23297
|
CanShowQuantitiesInput_SubscriptionFragment,
|
|
23247
23298
|
]);
|
|
23248
23299
|
const DEBOUNCE_TIME$1 = 1000;
|
|
23300
|
+
/**
|
|
23301
|
+
* Design note:
|
|
23302
|
+
* If the quantity is cleared by the user (quantity becomes undefined), we delete the quote.
|
|
23303
|
+
*
|
|
23304
|
+
* Rationale:
|
|
23305
|
+
* The user may next change the quantity for a charge on a different subscription, and we need to
|
|
23306
|
+
* allow creating a new quote/quoteChange in that context. Currently there is no way to create a
|
|
23307
|
+
* quoteChange of kind "update" without first calling `quoteSubscriptionUpdate`, so we delete the
|
|
23308
|
+
* existing quote to reset the flow.
|
|
23309
|
+
*/
|
|
23249
23310
|
const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription, setUpdatingChargeQuantityId, updatingChargeQuantityId, setErrorUpdatingQuantity, }) => {
|
|
23250
23311
|
// Context
|
|
23251
23312
|
const token = useToken();
|
|
@@ -23260,7 +23321,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23260
23321
|
const quote = readFragment(QuantityInput_QuoteFragment, maskedQuote);
|
|
23261
23322
|
// Hooks
|
|
23262
23323
|
const showErrorNotification = common.useErrorNotification();
|
|
23263
|
-
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
23324
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23264
23325
|
const quantityDisabled =
|
|
23265
23326
|
// If we are editing a quote, we disable the quantity input
|
|
23266
23327
|
// If we don't have a quantity, we disable the quantity input
|
|
@@ -23273,7 +23334,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23273
23334
|
!charge.selfServiceQuantity;
|
|
23274
23335
|
const value = quantity === undefined ? '' : quantity;
|
|
23275
23336
|
// Mutations
|
|
23276
|
-
const { mutate: createCharge } = reactQuery.useMutation({
|
|
23337
|
+
const { mutate: createCharge, isPending: isCreatingCharge } = reactQuery.useMutation({
|
|
23277
23338
|
mutationFn: quoteChargeCreate$1,
|
|
23278
23339
|
onSuccess: response => {
|
|
23279
23340
|
var _a, _b;
|
|
@@ -23288,7 +23349,23 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23288
23349
|
setErrorUpdatingQuantity(true);
|
|
23289
23350
|
},
|
|
23290
23351
|
});
|
|
23291
|
-
const
|
|
23352
|
+
const { mutate: deleteQuote, isPending: isDeletingQuote } = reactQuery.useMutation({
|
|
23353
|
+
mutationFn: quoteDelete,
|
|
23354
|
+
onSuccess: response => {
|
|
23355
|
+
var _a;
|
|
23356
|
+
const quoteId = (_a = response === null || response === void 0 ? void 0 : response.quote) === null || _a === void 0 ? void 0 : _a.id;
|
|
23357
|
+
if (!quoteId) {
|
|
23358
|
+
showErrorNotification('quoteId is required');
|
|
23359
|
+
return;
|
|
23360
|
+
}
|
|
23361
|
+
setQuoteQueryData(quoteId, null);
|
|
23362
|
+
setQuoteId(undefined);
|
|
23363
|
+
},
|
|
23364
|
+
onError: () => {
|
|
23365
|
+
setErrorUpdatingQuantity(true);
|
|
23366
|
+
},
|
|
23367
|
+
});
|
|
23368
|
+
const { mutate: createQuote, isPending: isCreatingQuote } = reactQuery.useMutation({
|
|
23292
23369
|
mutationFn: (subscriptionId) => quoteSubscriptionUpdate([subscriptionId], apiHost, token),
|
|
23293
23370
|
onSuccess: quote => {
|
|
23294
23371
|
var _a, _b, _c;
|
|
@@ -23316,7 +23393,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23316
23393
|
setErrorUpdatingQuantity(true);
|
|
23317
23394
|
},
|
|
23318
23395
|
});
|
|
23319
|
-
const updateQuoteCharge = reactQuery.useMutation({
|
|
23396
|
+
const { mutate: updateQuoteCharge, isPending: isUpdatingQuoteCharge } = reactQuery.useMutation({
|
|
23320
23397
|
mutationFn: ({ quoteChargeId, quantity, }) => {
|
|
23321
23398
|
if (!quoteChargeId)
|
|
23322
23399
|
throw new Error('quoteChargeId is required');
|
|
@@ -23338,26 +23415,35 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23338
23415
|
});
|
|
23339
23416
|
const onChangeQuantity = (value) => {
|
|
23340
23417
|
var _a;
|
|
23418
|
+
// Cancel all debounced functions first
|
|
23419
|
+
debouncedQuantityUpdate.cancel();
|
|
23420
|
+
debouncedDeleteQuote.cancel();
|
|
23341
23421
|
// Handle empty string - don't convert to 0, keep it as undefined
|
|
23342
23422
|
const quantity = value === '' ? undefined : isNaN(parseInt(value)) ? 0 : parseInt(value);
|
|
23343
23423
|
setQuantity(quantity);
|
|
23344
23424
|
if (quantity === undefined) {
|
|
23345
23425
|
setUpdatingChargeQuantityId(undefined);
|
|
23426
|
+
if (quoteId) {
|
|
23427
|
+
// Only delete the quote if it exists
|
|
23428
|
+
debouncedDeleteQuote(quoteId);
|
|
23429
|
+
}
|
|
23346
23430
|
}
|
|
23347
23431
|
else {
|
|
23348
23432
|
if (!(charge === null || charge === void 0 ? void 0 : charge.priceListChargeId)) {
|
|
23349
23433
|
showErrorNotification('Charge ID is not found');
|
|
23350
23434
|
return;
|
|
23351
23435
|
}
|
|
23352
|
-
//
|
|
23436
|
+
// Used to disable all other quantity inputs for this subscription
|
|
23353
23437
|
setUpdatingChargeQuantityId(getUpdatingChargeQuantityId(charge.priceListChargeId, subscription.id));
|
|
23354
23438
|
const quantityDelta = quantity - ((_a = charge.quantity) !== null && _a !== void 0 ? _a : 0);
|
|
23355
|
-
debouncedQuantityUpdate.
|
|
23356
|
-
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, quantity, subscription.id, quote, quoteId);
|
|
23439
|
+
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, subscription.id, quote, quoteId);
|
|
23357
23440
|
}
|
|
23358
23441
|
};
|
|
23359
|
-
const
|
|
23360
|
-
|
|
23442
|
+
const debouncedDeleteQuote = react.useCallback(lodashExports.debounce((quoteId) => {
|
|
23443
|
+
deleteQuote({ id: quoteId, apiHost, token });
|
|
23444
|
+
}, DEBOUNCE_TIME$1), []);
|
|
23445
|
+
const debouncedQuantityUpdate = react.useCallback(lodashExports.debounce((priceListChargeId, quantityDelta, subscriptionId, quote, quoteId) => {
|
|
23446
|
+
var _a;
|
|
23361
23447
|
if (quantityDelta === 0) {
|
|
23362
23448
|
setErrorUpdatingQuantity(true);
|
|
23363
23449
|
showErrorNotification('New quantity cannot be the same as current');
|
|
@@ -23365,37 +23451,22 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23365
23451
|
}
|
|
23366
23452
|
// If we are not editing a quote, we create a new one
|
|
23367
23453
|
if (quoteId === undefined) {
|
|
23368
|
-
createQuote
|
|
23454
|
+
createQuote(subscriptionId);
|
|
23369
23455
|
}
|
|
23370
23456
|
else {
|
|
23371
23457
|
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
23458
|
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
23459
|
if (quoteCharge) {
|
|
23374
|
-
updateQuoteCharge
|
|
23460
|
+
updateQuoteCharge({
|
|
23375
23461
|
quoteChargeId: quoteCharge.id,
|
|
23376
23462
|
quantity: quantityDelta,
|
|
23377
23463
|
});
|
|
23378
23464
|
}
|
|
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
23465
|
}
|
|
23395
23466
|
}, DEBOUNCE_TIME$1), []);
|
|
23396
|
-
return (jsxRuntime.
|
|
23397
|
-
|
|
23398
|
-
|
|
23467
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(antd.Input, { className: "bunny-text-right", disabled: quantityDisabled, onChange: e => {
|
|
23468
|
+
onChangeQuantity(e.target.value);
|
|
23469
|
+
}, style: { width: '96px' }, value: value }), jsxRuntime.jsx(QuoteIsLoadingUpdater, { quoteIsPending: isCreatingCharge || isDeletingQuote || isCreatingQuote || isUpdatingQuoteCharge })] }));
|
|
23399
23470
|
};
|
|
23400
23471
|
|
|
23401
23472
|
const QuantityChangeGridRow_SubscriptionChargeFragment = t(`
|
|
@@ -23522,6 +23593,46 @@ function invalidateSubscriptionsQueryKeys(queryClient, token) {
|
|
|
23522
23593
|
});
|
|
23523
23594
|
}
|
|
23524
23595
|
|
|
23596
|
+
const [QuoteRecalculateTaxesProvider, useQuoteRecalculateTaxes$2] = createValueContext();
|
|
23597
|
+
|
|
23598
|
+
const mutation$8 = t(`
|
|
23599
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
23600
|
+
quoteRecalculateTaxes(id: $id) {
|
|
23601
|
+
quote {
|
|
23602
|
+
...QuantityDrawer_QuoteFragment
|
|
23603
|
+
id
|
|
23604
|
+
}
|
|
23605
|
+
errors
|
|
23606
|
+
}
|
|
23607
|
+
}
|
|
23608
|
+
`, [QuantityDrawer_QuoteFragment]);
|
|
23609
|
+
const quoteRecalculateTaxes$1 = async ({ quoteId, apiHost, token, }) => {
|
|
23610
|
+
var _a;
|
|
23611
|
+
const response = await execute(mutation$8, { apiHost, token }, { id: quoteId });
|
|
23612
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
23613
|
+
};
|
|
23614
|
+
|
|
23615
|
+
const useQuoteRecalculateTaxes$1 = () => {
|
|
23616
|
+
const token = useToken();
|
|
23617
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
23618
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23619
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = reactQuery.useMutation({
|
|
23620
|
+
mutationFn: async ({ quoteId }) => {
|
|
23621
|
+
return await quoteRecalculateTaxes$1({ quoteId, apiHost, token });
|
|
23622
|
+
},
|
|
23623
|
+
onSuccess: quote => {
|
|
23624
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
23625
|
+
throw new Error('Quote ID is undefined');
|
|
23626
|
+
}
|
|
23627
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
23628
|
+
},
|
|
23629
|
+
});
|
|
23630
|
+
return {
|
|
23631
|
+
quoteRecalculateTaxesMutation,
|
|
23632
|
+
isRecalculatingTaxes,
|
|
23633
|
+
};
|
|
23634
|
+
};
|
|
23635
|
+
|
|
23525
23636
|
const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23526
23637
|
const token = useToken();
|
|
23527
23638
|
const queryClient = reactQuery.useQueryClient();
|
|
@@ -23531,6 +23642,8 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23531
23642
|
const [payModalVisible, setPayModalVisible] = react.useState(false);
|
|
23532
23643
|
const [updatingChargeQuantityId, setUpdatingChargeQuantityId] = react.useState(undefined);
|
|
23533
23644
|
const quote = useQuoteQueryData(quoteId);
|
|
23645
|
+
// Context
|
|
23646
|
+
const onRecalculateTaxes = useQuoteRecalculateTaxes$2();
|
|
23534
23647
|
// Handlers
|
|
23535
23648
|
const onSuccess = () => {
|
|
23536
23649
|
setQuantityDrawerOpen(false);
|
|
@@ -23560,10 +23673,11 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23560
23673
|
const handleOpenCheckout = () => {
|
|
23561
23674
|
setPayModalVisible(true);
|
|
23562
23675
|
};
|
|
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 })] }));
|
|
23676
|
+
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
23677
|
};
|
|
23565
23678
|
const QuantityDrawer = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23566
|
-
|
|
23679
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes$1();
|
|
23680
|
+
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
23681
|
};
|
|
23568
23682
|
|
|
23569
23683
|
const useCancelSubscription = () => {
|
|
@@ -23827,14 +23941,27 @@ const SubscriptionCardActions = ({ onChangePlanClick, onCancelSubscriptionClick,
|
|
|
23827
23941
|
const isInTrial = isSubscriptionTrial(subscription);
|
|
23828
23942
|
const isTrialExpired = isSubscriptionTrialExpired(subscription);
|
|
23829
23943
|
const isActiveOrPending = isSubscriptionActiveOrPending(subscription);
|
|
23944
|
+
const getButtonLabel = () => {
|
|
23945
|
+
if (isInTrial) {
|
|
23946
|
+
return 'Upgrade from trial';
|
|
23947
|
+
}
|
|
23948
|
+
if (isTrialExpired) {
|
|
23949
|
+
return 'Upgrade';
|
|
23950
|
+
}
|
|
23951
|
+
// If the subscription is an addon, we should show the "Adjust plan" button since we don't support changing add-on plans.
|
|
23952
|
+
if (subscription.priceList.plan.addon === true) {
|
|
23953
|
+
return 'Adjust plan';
|
|
23954
|
+
}
|
|
23955
|
+
return 'Change plan';
|
|
23956
|
+
};
|
|
23830
23957
|
if (isPaymentMethodLoading)
|
|
23831
23958
|
return null;
|
|
23832
23959
|
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
23960
|
onChangePlanClick &&
|
|
23834
|
-
(isActiveOrPending || isInTrial || isTrialExpired) && (jsxRuntime.jsx(antd.Button, { onClick: () => onChangePlanClick(subscription), type: 'primary', children:
|
|
23961
|
+
(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
23962
|
};
|
|
23836
23963
|
|
|
23837
|
-
const query$
|
|
23964
|
+
const query$4 = t(`
|
|
23838
23965
|
query priceListChangeOptions($productId: ID!) {
|
|
23839
23966
|
priceListChangeOptions(productId: $productId) {
|
|
23840
23967
|
...SubscriptionCardActions_PriceListChangeOptionsFragment
|
|
@@ -23842,7 +23969,7 @@ const query$2 = t(`
|
|
|
23842
23969
|
}
|
|
23843
23970
|
`, [SubscriptionCardActions_PriceListChangeOptionsFragment]);
|
|
23844
23971
|
const getPriceListChangeOptions$1 = async ({ apiHost, productId, token, }) => {
|
|
23845
|
-
const response = await execute(query$
|
|
23972
|
+
const response = await execute(query$4, { apiHost, token }, { productId });
|
|
23846
23973
|
return response.priceListChangeOptions;
|
|
23847
23974
|
};
|
|
23848
23975
|
|
|
@@ -23876,7 +24003,7 @@ const getSubscriptionStatusText = (subscription) => {
|
|
|
23876
24003
|
return `Trial expires on ${common.formatDate(trialEndDate)}`;
|
|
23877
24004
|
}
|
|
23878
24005
|
}
|
|
23879
|
-
if (evergreen) {
|
|
24006
|
+
if (evergreen && subscription.state === t.scalar('SubscriptionState', 'ACTIVE')) {
|
|
23880
24007
|
return `Renews on ${common.formatDate(endDate)}`;
|
|
23881
24008
|
}
|
|
23882
24009
|
return `Ends on ${common.formatDate(endDate || trialEndDate)}`;
|
|
@@ -23954,40 +24081,66 @@ const formatNumber = (num, decimals = 2) => {
|
|
|
23954
24081
|
});
|
|
23955
24082
|
};
|
|
23956
24083
|
|
|
24084
|
+
const getPricingModelDescription = (pricingModel) => {
|
|
24085
|
+
switch (pricingModel) {
|
|
24086
|
+
case 'TIERED':
|
|
24087
|
+
return 'units in each tier are priced separately.';
|
|
24088
|
+
case 'VOLUME':
|
|
24089
|
+
return 'the highest tier reached prices all units.';
|
|
24090
|
+
case 'BANDS':
|
|
24091
|
+
return 'the quantity indexes to a flat price.';
|
|
24092
|
+
default:
|
|
24093
|
+
return '';
|
|
24094
|
+
}
|
|
24095
|
+
};
|
|
24096
|
+
|
|
24097
|
+
const getPricingModelTitle = (pricingModel) => {
|
|
24098
|
+
switch (pricingModel) {
|
|
24099
|
+
case 'TIERED':
|
|
24100
|
+
return 'Tiered';
|
|
24101
|
+
case 'VOLUME':
|
|
24102
|
+
return 'Volume';
|
|
24103
|
+
case 'BANDS':
|
|
24104
|
+
return 'Bands';
|
|
24105
|
+
default:
|
|
24106
|
+
return '';
|
|
24107
|
+
}
|
|
24108
|
+
};
|
|
24109
|
+
|
|
23957
24110
|
const StyledTable = styled(antd.Table) `
|
|
23958
24111
|
.ant-table-cell {
|
|
23959
24112
|
border-bottom: none !important;
|
|
23960
24113
|
}
|
|
23961
24114
|
`;
|
|
23962
|
-
const TieredDisplayDropdown = ({ priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
24115
|
+
const TieredDisplayDropdown = ({ pricingModel, priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
23963
24116
|
const onlyHasOneTier = (priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers.length) === 1;
|
|
23964
24117
|
const dropdownTrigger = (jsxRuntime.jsx("div", { className: `w-full ${onlyHasOneTier ? '' : 'underline cursor-pointer'}`, children: truncatedText }));
|
|
23965
24118
|
if (onlyHasOneTier) {
|
|
23966
24119
|
return dropdownTrigger;
|
|
23967
24120
|
}
|
|
23968
24121
|
return (jsxRuntime.jsx(antd.Dropdown, { popupRender: () => {
|
|
23969
|
-
return (jsxRuntime.
|
|
23970
|
-
|
|
23971
|
-
|
|
23972
|
-
|
|
23973
|
-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
23979
|
-
|
|
24122
|
+
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: [
|
|
24123
|
+
{
|
|
24124
|
+
dataIndex: 'starts',
|
|
24125
|
+
title: 'From # of units',
|
|
24126
|
+
align: 'right',
|
|
24127
|
+
render: (_, record, index) => {
|
|
24128
|
+
record = record;
|
|
24129
|
+
const nextRecord = priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers[index + 1];
|
|
24130
|
+
const starts = record.starts;
|
|
24131
|
+
const ends = (nextRecord === null || nextRecord === void 0 ? void 0 : nextRecord.starts) ? nextRecord.starts - 1 : '+';
|
|
24132
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [formatNumber(starts, 0), typeof ends === 'number' ? formatNumber(ends, 0) : '+'] }));
|
|
24133
|
+
},
|
|
23980
24134
|
},
|
|
23981
|
-
|
|
23982
|
-
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
|
|
23986
|
-
|
|
23987
|
-
|
|
24135
|
+
{
|
|
24136
|
+
dataIndex: 'price',
|
|
24137
|
+
title: 'Unit price',
|
|
24138
|
+
align: 'right',
|
|
24139
|
+
render: value => {
|
|
24140
|
+
return jsxRuntime.jsx(jsxRuntime.Fragment, { children: common.formatCurrency(value, currencyId, priceDecimals) });
|
|
24141
|
+
},
|
|
23988
24142
|
},
|
|
23989
|
-
}
|
|
23990
|
-
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" }) }));
|
|
24143
|
+
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" })] }));
|
|
23991
24144
|
}, children: dropdownTrigger }));
|
|
23992
24145
|
};
|
|
23993
24146
|
|
|
@@ -24038,7 +24191,7 @@ const SubscriptionChargeUnitPrice = ({ charge, currencyId, }) => {
|
|
|
24038
24191
|
? '-'
|
|
24039
24192
|
: common.formatCurrency(charge.discountedPrice, currencyId, charge.priceDecimals);
|
|
24040
24193
|
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) }));
|
|
24194
|
+
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
24195
|
};
|
|
24043
24196
|
|
|
24044
24197
|
const { Text: Text$e } = antd.Typography;
|
|
@@ -24175,7 +24328,7 @@ const SubscriptionCardDesktopRow = ({ charge, chargeIndex, charges, currencyId,
|
|
|
24175
24328
|
: (_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
24329
|
};
|
|
24177
24330
|
|
|
24178
|
-
function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, subscription, showInactive, }) {
|
|
24331
|
+
function AddonSubscriptionsCards({ onCancelSubscriptionClick, onChangePlanClick, subscriptions, subscription, showInactive, }) {
|
|
24179
24332
|
const addonSubscriptions = findAddonSubscriptions(subscription, subscriptions);
|
|
24180
24333
|
if (addonSubscriptions.length === 0) {
|
|
24181
24334
|
return null;
|
|
@@ -24184,7 +24337,7 @@ function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, sub
|
|
|
24184
24337
|
if (!showInactive && isSubscriptionNotActive(addonSubscription))
|
|
24185
24338
|
return null;
|
|
24186
24339
|
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));
|
|
24340
|
+
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
24341
|
}) }));
|
|
24189
24342
|
}
|
|
24190
24343
|
|
|
@@ -24243,8 +24396,8 @@ const SubscriptionsList = ({ showInactive, onChangePlanClick, onCancelSubscripti
|
|
|
24243
24396
|
if (!showInactive && isSubscriptionNotActive(subscription))
|
|
24244
24397
|
return null;
|
|
24245
24398
|
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));
|
|
24399
|
+
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));
|
|
24400
|
+
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
24401
|
}) }));
|
|
24249
24402
|
};
|
|
24250
24403
|
|
|
@@ -24315,7 +24468,7 @@ const FormattedQuoteFields_QuoteFragment = t(`
|
|
|
24315
24468
|
}
|
|
24316
24469
|
}
|
|
24317
24470
|
`);
|
|
24318
|
-
const query$
|
|
24471
|
+
const query$3 = t(`
|
|
24319
24472
|
query quote($id: ID, $includeHtmlField: Boolean!) {
|
|
24320
24473
|
quote(id: $id) {
|
|
24321
24474
|
...FormattedQuoteFields_QuoteFragment @include(if: $includeHtmlField)
|
|
@@ -24324,7 +24477,7 @@ const query$1 = t(`
|
|
|
24324
24477
|
}
|
|
24325
24478
|
`, [FormattedQuoteFields_QuoteFragment, QuoteContext_QuoteFragment]);
|
|
24326
24479
|
const getQuote = async ({ id, token, apiHost, includeHtmlField = false, }) => {
|
|
24327
|
-
const response = await execute(query$
|
|
24480
|
+
const response = await execute(query$3, { apiHost, token }, { id, includeHtmlField });
|
|
24328
24481
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
24329
24482
|
};
|
|
24330
24483
|
|
|
@@ -24429,7 +24582,7 @@ const calculateNewQuantity = (priceListCharge, currentQuantity = 1) => {
|
|
|
24429
24582
|
return quantityMin;
|
|
24430
24583
|
};
|
|
24431
24584
|
|
|
24432
|
-
const mutation$
|
|
24585
|
+
const mutation$7 = t(`
|
|
24433
24586
|
mutation QuoteChangeUpdate($id: ID!, $charges: [QuoteChargeAttributes!]!) {
|
|
24434
24587
|
quoteChangeUpdate(id: $id, charges: $charges) {
|
|
24435
24588
|
quoteChange {
|
|
@@ -24443,7 +24596,7 @@ const mutation$1 = t(`
|
|
|
24443
24596
|
`, [QuoteContext_QuoteFragment]);
|
|
24444
24597
|
const quoteChangeUpdate = async ({ quoteChangeId, charges, apiHost, token, }) => {
|
|
24445
24598
|
var _a, _b;
|
|
24446
|
-
const response = await execute(mutation$
|
|
24599
|
+
const response = await execute(mutation$7, {
|
|
24447
24600
|
apiHost,
|
|
24448
24601
|
token,
|
|
24449
24602
|
}, {
|
|
@@ -24499,6 +24652,19 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24499
24652
|
};
|
|
24500
24653
|
}
|
|
24501
24654
|
|
|
24655
|
+
const useSetQuoteQueryData = () => {
|
|
24656
|
+
const token = useToken();
|
|
24657
|
+
const queryClient = reactQuery.useQueryClient();
|
|
24658
|
+
const setQuoteQueryData = (quoteId, quote) => {
|
|
24659
|
+
queryClient.setQueryData(common.QueryKeyFactory.default.createObjectKey({
|
|
24660
|
+
id: quoteId,
|
|
24661
|
+
objectName: 'editingQuote',
|
|
24662
|
+
token,
|
|
24663
|
+
}), quote);
|
|
24664
|
+
};
|
|
24665
|
+
return { setQuoteQueryData };
|
|
24666
|
+
};
|
|
24667
|
+
|
|
24502
24668
|
// Functionality:
|
|
24503
24669
|
// 1: keep track of quantities set for features based on feature.id
|
|
24504
24670
|
// a. copy those quantities over to charges with same feature when initializing
|
|
@@ -24511,9 +24677,9 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24511
24677
|
const showErrorNotification = common.useErrorNotification();
|
|
24512
24678
|
const DEBOUNCE_TIME = 1000;
|
|
24513
24679
|
const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
24514
|
-
const queryClient = reactQuery.useQueryClient();
|
|
24515
24680
|
const token = useToken();
|
|
24516
24681
|
const { apiHost } = react.useContext(BunnyContext);
|
|
24682
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24517
24683
|
// Derived state
|
|
24518
24684
|
const selectedPriceListQuoteChange = react.useMemo(() => {
|
|
24519
24685
|
var _a;
|
|
@@ -24532,23 +24698,27 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24532
24698
|
});
|
|
24533
24699
|
},
|
|
24534
24700
|
onSuccess: quoteChange => {
|
|
24535
|
-
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
|
|
24540
|
-
}
|
|
24701
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24702
|
+
throw new Error('Quote ID is undefined');
|
|
24703
|
+
}
|
|
24704
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote)) {
|
|
24705
|
+
throw new Error('Quote is undefined');
|
|
24706
|
+
}
|
|
24707
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote);
|
|
24541
24708
|
},
|
|
24542
24709
|
});
|
|
24543
24710
|
function handleUpdateQuoteQuantities(featureQuantities) {
|
|
24544
24711
|
if (!selectedPriceListQuoteChange) {
|
|
24545
|
-
|
|
24712
|
+
console.error('Quote change is undefined');
|
|
24713
|
+
return;
|
|
24546
24714
|
}
|
|
24547
24715
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24548
|
-
|
|
24716
|
+
console.error('Quote ID is undefined');
|
|
24717
|
+
return;
|
|
24549
24718
|
}
|
|
24550
24719
|
if (!(selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.id)) {
|
|
24551
|
-
|
|
24720
|
+
console.error('Quote change ID is undefined');
|
|
24721
|
+
return;
|
|
24552
24722
|
}
|
|
24553
24723
|
const featureIdsToUpdate = Object.keys(featureQuantities).filter(featureId => {
|
|
24554
24724
|
// If the quantities differ, then update quote with the quantities present in useFeatureQuantities
|
|
@@ -24560,20 +24730,24 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24560
24730
|
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
24731
|
return quoteCharge !== undefined && localAndQuoteQuantitiesDiffer;
|
|
24562
24732
|
});
|
|
24563
|
-
const charges = featureIdsToUpdate
|
|
24733
|
+
const charges = featureIdsToUpdate
|
|
24734
|
+
.map(featureId => {
|
|
24564
24735
|
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
24736
|
const quantity = getFeatureQuantity(featureId, featureQuantities);
|
|
24566
24737
|
if (!quantity) {
|
|
24567
|
-
|
|
24738
|
+
console.error('Quantity is undefined');
|
|
24739
|
+
return;
|
|
24568
24740
|
}
|
|
24569
24741
|
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id)) {
|
|
24570
|
-
|
|
24742
|
+
console.error('Quote charge for featureId is undefined');
|
|
24743
|
+
return;
|
|
24571
24744
|
}
|
|
24572
24745
|
return {
|
|
24573
24746
|
id: quoteCharge.id,
|
|
24574
24747
|
quantity: quantity,
|
|
24575
24748
|
};
|
|
24576
|
-
})
|
|
24749
|
+
})
|
|
24750
|
+
.filter(charge => charge !== undefined);
|
|
24577
24751
|
if (charges.length === 0) {
|
|
24578
24752
|
return;
|
|
24579
24753
|
}
|
|
@@ -24641,6 +24815,44 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24641
24815
|
};
|
|
24642
24816
|
};
|
|
24643
24817
|
|
|
24818
|
+
const mutation$6 = t(`
|
|
24819
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
24820
|
+
quoteRecalculateTaxes(id: $id) {
|
|
24821
|
+
quote {
|
|
24822
|
+
...QuoteContext_QuoteFragment
|
|
24823
|
+
id
|
|
24824
|
+
}
|
|
24825
|
+
errors
|
|
24826
|
+
}
|
|
24827
|
+
}
|
|
24828
|
+
`, [QuoteContext_QuoteFragment]);
|
|
24829
|
+
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
24830
|
+
var _a;
|
|
24831
|
+
const response = await execute(mutation$6, { apiHost, token }, { id: quoteId });
|
|
24832
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
24833
|
+
};
|
|
24834
|
+
|
|
24835
|
+
const useQuoteRecalculateTaxes = () => {
|
|
24836
|
+
const token = useToken();
|
|
24837
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
24838
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24839
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = reactQuery.useMutation({
|
|
24840
|
+
mutationFn: async ({ quoteId }) => {
|
|
24841
|
+
return await quoteRecalculateTaxes({ quoteId, apiHost, token });
|
|
24842
|
+
},
|
|
24843
|
+
onSuccess: quote => {
|
|
24844
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24845
|
+
throw new Error('Quote ID is undefined');
|
|
24846
|
+
}
|
|
24847
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
24848
|
+
},
|
|
24849
|
+
});
|
|
24850
|
+
return {
|
|
24851
|
+
quoteRecalculateTaxesMutation,
|
|
24852
|
+
isRecalculatingTaxes,
|
|
24853
|
+
};
|
|
24854
|
+
};
|
|
24855
|
+
|
|
24644
24856
|
function useFeatureAddonsPending() {
|
|
24645
24857
|
const [featureAddonsLoading, setFeatureAddonsLoading] = react.useState([]);
|
|
24646
24858
|
const addFeatureAddonLoading = (featureAddonId) => {
|
|
@@ -24664,6 +24876,7 @@ function QuoteProvider({ children }) {
|
|
|
24664
24876
|
// Hooks
|
|
24665
24877
|
const token = useToken();
|
|
24666
24878
|
const { isFeatureAddonsLoading, addFeatureAddonLoading, removeFeatureAddonLoading } = useFeatureAddonsPending();
|
|
24879
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes();
|
|
24667
24880
|
const { quote: maskedQuote, isQuotePending } = useQuoteCreate({
|
|
24668
24881
|
upgradingSubscription,
|
|
24669
24882
|
selectedPriceList: selectedPriceList,
|
|
@@ -24699,6 +24912,7 @@ function QuoteProvider({ children }) {
|
|
|
24699
24912
|
onChangeSelectedPriceList: handleChangeSelectedPriceList,
|
|
24700
24913
|
onChangeQuantity,
|
|
24701
24914
|
getFeatureQuantity,
|
|
24915
|
+
onRecalculateTaxes: (id) => quoteRecalculateTaxesMutation({ quoteId: id }),
|
|
24702
24916
|
}, children: children }));
|
|
24703
24917
|
}
|
|
24704
24918
|
|
|
@@ -24725,40 +24939,6 @@ function priceDescriptionString({ unitName, showPriceAsMonthly, periodMonths, pr
|
|
|
24725
24939
|
return `Per ${unitName && !priceListHasFlatFeeCharges ? `${unitName.toLowerCase()} / ` : ''}${showPriceAsMonthly ? 'month' : periodLabel}`;
|
|
24726
24940
|
}
|
|
24727
24941
|
|
|
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
24942
|
const { Text: Text$b } = antd.Typography;
|
|
24763
24943
|
const PriceTierPrice = ({ currencyId, priceDecimals, tier, }) => {
|
|
24764
24944
|
return (jsxRuntime.jsx(Text$b, { className: "bunny-text-white", children: formatCurrency(tier.price, currencyId, priceDecimals) }));
|
|
@@ -24782,32 +24962,6 @@ const PriceTierRow = ({ tier: maskedTier, nextTier: maskedNextTier, }) => {
|
|
|
24782
24962
|
return jsxRuntime.jsx(Text$a, { className: "bunny-text-white", children: text });
|
|
24783
24963
|
};
|
|
24784
24964
|
|
|
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
24965
|
const { Text: Text$9 } = antd.Typography;
|
|
24812
24966
|
const ChargePriceTiers_PriceListChargeFragment = t(`
|
|
24813
24967
|
fragment ChargePriceTiers_PriceListChargeFragment on PriceListCharge {
|
|
@@ -25442,57 +25596,13 @@ const getAvailablePlansAndPriceLists = ({ availablePriceLists, priceListChangeOp
|
|
|
25442
25596
|
return {
|
|
25443
25597
|
availablePriceListsArray,
|
|
25444
25598
|
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;
|
|
25599
|
+
};
|
|
25600
|
+
};
|
|
25601
|
+
const everythingInPlusString = ({ priceList }) => {
|
|
25602
|
+
return `Everything in ${priceList.plan.name}, plus`;
|
|
25493
25603
|
};
|
|
25494
25604
|
|
|
25495
|
-
const mutation = t(`
|
|
25605
|
+
const mutation$5 = t(`
|
|
25496
25606
|
mutation QuoteChargeDelete($quoteChargeId: ID!) {
|
|
25497
25607
|
quoteChargeDelete(quoteChargeId: $quoteChargeId) {
|
|
25498
25608
|
errors
|
|
@@ -25510,21 +25620,76 @@ const mutation = t(`
|
|
|
25510
25620
|
`, [QuoteContext_QuoteFragment]);
|
|
25511
25621
|
const quoteChargeDelete = async ({ quoteChargeId, token, apiHost }) => {
|
|
25512
25622
|
var _a, _b, _c, _d;
|
|
25513
|
-
const response = await execute(mutation, { apiHost, token }, { quoteChargeId });
|
|
25623
|
+
const response = await execute(mutation$5, { apiHost, token }, { quoteChargeId });
|
|
25514
25624
|
if ((_a = response.quoteChargeDelete) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
25515
25625
|
throw new Error((_c = (_b = response.quoteChargeDelete) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c[0]);
|
|
25516
25626
|
}
|
|
25517
25627
|
return (_d = response.quoteChargeDelete) === null || _d === void 0 ? void 0 : _d.quoteCharge;
|
|
25518
25628
|
};
|
|
25519
25629
|
|
|
25520
|
-
const
|
|
25630
|
+
const mutation$4 = t(`
|
|
25631
|
+
mutation QuoteChargeCreate(
|
|
25632
|
+
$quoteChangeId: ID!
|
|
25633
|
+
$startDate: ISO8601Date!
|
|
25634
|
+
$endDate: ISO8601Date
|
|
25635
|
+
$priceListChargeId: ID
|
|
25636
|
+
$subscriptionChargeId: ID
|
|
25637
|
+
$price: Float
|
|
25638
|
+
$quantity: Int
|
|
25639
|
+
) {
|
|
25640
|
+
quoteChargeCreate(
|
|
25641
|
+
endDate: $endDate
|
|
25642
|
+
price: $price
|
|
25643
|
+
priceListChargeId: $priceListChargeId
|
|
25644
|
+
quantity: $quantity
|
|
25645
|
+
quoteChangeId: $quoteChangeId
|
|
25646
|
+
startDate: $startDate
|
|
25647
|
+
subscriptionChargeId: $subscriptionChargeId
|
|
25648
|
+
) {
|
|
25649
|
+
quoteCharge {
|
|
25650
|
+
quoteChange {
|
|
25651
|
+
id
|
|
25652
|
+
quoteId
|
|
25653
|
+
quote {
|
|
25654
|
+
...QuoteContext_QuoteFragment
|
|
25655
|
+
}
|
|
25656
|
+
}
|
|
25657
|
+
id
|
|
25658
|
+
}
|
|
25659
|
+
}
|
|
25660
|
+
}
|
|
25661
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25662
|
+
const quoteChargeCreate = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
25663
|
+
var _a;
|
|
25664
|
+
const response = await execute(mutation$4, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
25665
|
+
return (_a = response === null || response === void 0 ? void 0 : response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
25666
|
+
};
|
|
25667
|
+
|
|
25668
|
+
const useQuoteUpdateFeatureAddon = (maskedQuote, featureAddon) => {
|
|
25521
25669
|
const { apiHost } = react.useContext(BunnyContext);
|
|
25522
25670
|
const { addFeatureAddonLoading, removeFeatureAddonLoading } = react.useContext(QuoteContext);
|
|
25523
25671
|
const token = useToken();
|
|
25524
|
-
const
|
|
25672
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
25673
|
+
// Read fragments
|
|
25674
|
+
const quote = readFragment(useQuoteUpdateFeatureAddon_QuoteFragment, maskedQuote);
|
|
25525
25675
|
const addedQuoteChargeId = react.useRef();
|
|
25526
25676
|
function handleAddFeatureAddon() {
|
|
25527
|
-
|
|
25677
|
+
if (!token)
|
|
25678
|
+
throw new Error('Token is required');
|
|
25679
|
+
if (!quote)
|
|
25680
|
+
throw new Error('Editing quote is required');
|
|
25681
|
+
const quoteChangeId = findQuoteChangeForFeatureAddon(quote);
|
|
25682
|
+
if (!quoteChangeId)
|
|
25683
|
+
throw new Error('No available quote change for feature add-on');
|
|
25684
|
+
console.log('quote', quote);
|
|
25685
|
+
console.log('startDate', quote === null || quote === void 0 ? void 0 : quote.startDate);
|
|
25686
|
+
quoteChargeCreateMutation({
|
|
25687
|
+
quoteChangeId: quoteChangeId.id,
|
|
25688
|
+
priceListChargeId: featureAddon.id,
|
|
25689
|
+
startDate: quote === null || quote === void 0 ? void 0 : quote.startDate,
|
|
25690
|
+
apiHost,
|
|
25691
|
+
token,
|
|
25692
|
+
});
|
|
25528
25693
|
}
|
|
25529
25694
|
function handleRemoveFeatureAddon() {
|
|
25530
25695
|
if (!addedQuoteChargeId.current)
|
|
@@ -25532,30 +25697,16 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25532
25697
|
quoteChargeDeleteMutation({ quoteChargeId: addedQuoteChargeId.current });
|
|
25533
25698
|
}
|
|
25534
25699
|
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);
|
|
25700
|
+
mutationFn: quoteChargeCreate,
|
|
25701
|
+
onSuccess: quoteCharge => {
|
|
25702
|
+
addedQuoteChargeId.current = quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id;
|
|
25703
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25704
|
+
throw new Error('Quote ID is undefined');
|
|
25705
|
+
}
|
|
25706
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25707
|
+
throw new Error('Quote is undefined');
|
|
25708
|
+
}
|
|
25709
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25559
25710
|
},
|
|
25560
25711
|
});
|
|
25561
25712
|
const { mutate: quoteChargeDeleteMutation, isPending: isDeletingFeatureAddon } = reactQuery.useMutation({
|
|
@@ -25565,11 +25716,13 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25565
25716
|
},
|
|
25566
25717
|
onSuccess: quoteCharge => {
|
|
25567
25718
|
addedQuoteChargeId.current = undefined;
|
|
25568
|
-
|
|
25569
|
-
|
|
25570
|
-
|
|
25571
|
-
|
|
25572
|
-
|
|
25719
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25720
|
+
throw new Error('Quote ID is undefined');
|
|
25721
|
+
}
|
|
25722
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25723
|
+
throw new Error('Quote is undefined');
|
|
25724
|
+
}
|
|
25725
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25573
25726
|
},
|
|
25574
25727
|
});
|
|
25575
25728
|
const isPending = isCreatingFeatureAddon || isDeletingFeatureAddon;
|
|
@@ -25649,10 +25802,11 @@ const FeatureAddonRow_PriceListChargeFragment = t(`
|
|
|
25649
25802
|
}
|
|
25650
25803
|
`, [isAddonPurchased_PriceListChargeFragment, PricingTooltip_PriceListChargeFragment]);
|
|
25651
25804
|
function FeatureAddonRow({ featureAddon: maskedFeatureAddon, priceList: maskedPriceList, }) {
|
|
25805
|
+
const { quote: maskedQuote, selectedPriceList } = react.useContext(QuoteContext);
|
|
25652
25806
|
// Read fragments
|
|
25653
25807
|
const featureAddon = readFragment(FeatureAddonRow_PriceListChargeFragment, maskedFeatureAddon);
|
|
25654
25808
|
const priceList = readFragment(FeatureAddonRow_PriceListFragment, maskedPriceList);
|
|
25655
|
-
const
|
|
25809
|
+
const quote = readFragment(FeatureAddonRow_QuoteFragment, maskedQuote);
|
|
25656
25810
|
const { handleAddFeatureAddon, handleRemoveFeatureAddon, isPending, isChecked } = useQuoteUpdateFeatureAddon(quote, featureAddon);
|
|
25657
25811
|
const { brandColor } = useBrand();
|
|
25658
25812
|
const { upgradingSubscription } = react.useContext(SubscriptionsContext);
|
|
@@ -25867,107 +26021,84 @@ function AddonPlanModal({ onClose, priceList: maskedPriceList, }) {
|
|
|
25867
26021
|
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
26022
|
}
|
|
25869
26023
|
|
|
25870
|
-
const
|
|
25871
|
-
${
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
) {
|
|
25877
|
-
|
|
25878
|
-
|
|
25879
|
-
|
|
25880
|
-
|
|
25881
|
-
|
|
25882
|
-
|
|
25883
|
-
|
|
25884
|
-
id
|
|
25885
|
-
quote {
|
|
25886
|
-
...QuoteFields
|
|
26024
|
+
const mutation$3 = t(`
|
|
26025
|
+
mutation QuoteChangeCreate($quoteId: ID!, $priceListId: ID!, $parentQuoteChangeId: ID!) {
|
|
26026
|
+
quoteChangeCreate(
|
|
26027
|
+
quoteId: $quoteId
|
|
26028
|
+
priceListId: $priceListId
|
|
26029
|
+
parentQuoteChangeId: $parentQuoteChangeId
|
|
26030
|
+
) {
|
|
26031
|
+
errors
|
|
26032
|
+
quoteChange {
|
|
26033
|
+
id
|
|
26034
|
+
quote {
|
|
26035
|
+
...QuoteContext_QuoteFragment
|
|
26036
|
+
}
|
|
26037
|
+
}
|
|
25887
26038
|
}
|
|
25888
26039
|
}
|
|
25889
|
-
|
|
25890
|
-
}
|
|
25891
|
-
`;
|
|
26040
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25892
26041
|
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;
|
|
26042
|
+
const response = await execute(mutation$3, { apiHost, token }, { parentQuoteChangeId, priceListId, quoteId });
|
|
25908
26043
|
return response.quoteChangeCreate;
|
|
25909
26044
|
};
|
|
25910
26045
|
|
|
25911
|
-
const
|
|
25912
|
-
${
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
26046
|
+
const mutation$2 = t(`
|
|
26047
|
+
mutation QuoteChangeDelete($id: ID!) {
|
|
26048
|
+
quoteChangeDelete(id: $id) {
|
|
26049
|
+
errors
|
|
26050
|
+
quoteChange {
|
|
26051
|
+
quote {
|
|
26052
|
+
...QuoteContext_QuoteFragment
|
|
26053
|
+
}
|
|
25919
26054
|
}
|
|
25920
26055
|
}
|
|
25921
26056
|
}
|
|
25922
|
-
|
|
25923
|
-
`;
|
|
26057
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25924
26058
|
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;
|
|
26059
|
+
const response = await execute(mutation$2, { apiHost, token }, { id });
|
|
25938
26060
|
return response.quoteChangeDelete;
|
|
25939
26061
|
};
|
|
25940
26062
|
|
|
25941
|
-
const useToggleAddonPlan = (
|
|
26063
|
+
const useToggleAddonPlan = (maskedQuote, addonPriceListId, selectedPriceList, setIsAddonPlanLoading) => {
|
|
25942
26064
|
const token = useToken();
|
|
25943
26065
|
const isAdded = react.useRef(false);
|
|
25944
|
-
const queryClient = reactQuery.useQueryClient();
|
|
25945
26066
|
const { apiHost } = react.useContext(BunnyContext);
|
|
26067
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
26068
|
+
// Read fragments
|
|
26069
|
+
const quote = readFragment(useToggleAddonPlan_QuoteFragment, maskedQuote);
|
|
25946
26070
|
const parentQuoteChange = react.useMemo(() => {
|
|
25947
|
-
|
|
26071
|
+
var _a;
|
|
26072
|
+
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
26073
|
}, [quote, selectedPriceList]);
|
|
25949
26074
|
const { mutate: addAddonQuoteChange, isPending: isAddingAddonQuoteChange } = reactQuery.useMutation({
|
|
25950
26075
|
mutationFn: quoteChangeCreate,
|
|
25951
|
-
onSuccess:
|
|
26076
|
+
onSuccess: quoteChangeCreate => {
|
|
26077
|
+
var _a;
|
|
25952
26078
|
isAdded.current = true;
|
|
25953
|
-
const updatedQuote = quoteChangeCreate.quoteChange.quote;
|
|
25954
|
-
|
|
25955
|
-
|
|
25956
|
-
|
|
25957
|
-
|
|
25958
|
-
|
|
26079
|
+
const updatedQuote = (_a = quoteChangeCreate === null || quoteChangeCreate === void 0 ? void 0 : quoteChangeCreate.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26080
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26081
|
+
throw new Error('Updated quote ID not found');
|
|
26082
|
+
}
|
|
26083
|
+
if (!updatedQuote) {
|
|
26084
|
+
throw new Error('Updated quote not found');
|
|
26085
|
+
}
|
|
26086
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25959
26087
|
},
|
|
25960
26088
|
});
|
|
25961
26089
|
const { mutate: deleteQuoteChange, isPending: isDeletingQuoteChange } = reactQuery.useMutation({
|
|
25962
26090
|
mutationFn: quoteChangeDelete,
|
|
25963
|
-
onSuccess:
|
|
26091
|
+
onSuccess: quoteChangeDelete => {
|
|
26092
|
+
var _a;
|
|
25964
26093
|
isAdded.current = false;
|
|
25965
|
-
const updatedQuote = quoteChangeDelete.quoteChange.quote;
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
26094
|
+
const updatedQuote = (_a = quoteChangeDelete === null || quoteChangeDelete === void 0 ? void 0 : quoteChangeDelete.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26095
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26096
|
+
throw new Error('Updated quote ID not found');
|
|
26097
|
+
}
|
|
26098
|
+
if (!updatedQuote) {
|
|
26099
|
+
throw new Error('Updated quote not found');
|
|
26100
|
+
}
|
|
26101
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25971
26102
|
},
|
|
25972
26103
|
});
|
|
25973
26104
|
function handleAddAddonQuoteChange() {
|
|
@@ -25977,6 +26108,9 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25977
26108
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25978
26109
|
throw new Error('Quote ID not found');
|
|
25979
26110
|
}
|
|
26111
|
+
if (!parentQuoteChange.id) {
|
|
26112
|
+
throw new Error('Parent quote change ID not found');
|
|
26113
|
+
}
|
|
25980
26114
|
addAddonQuoteChange({
|
|
25981
26115
|
parentQuoteChangeId: parentQuoteChange.id,
|
|
25982
26116
|
priceListId: addonPriceListId,
|
|
@@ -25986,9 +26120,10 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25986
26120
|
});
|
|
25987
26121
|
}
|
|
25988
26122
|
function handleDeleteQuoteChange() {
|
|
25989
|
-
|
|
25990
|
-
|
|
25991
|
-
|
|
26123
|
+
var _a;
|
|
26124
|
+
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; });
|
|
26125
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id)) {
|
|
26126
|
+
throw new Error('Quote change ID not found');
|
|
25992
26127
|
}
|
|
25993
26128
|
deleteQuoteChange({
|
|
25994
26129
|
id: quoteChange.id,
|
|
@@ -26022,6 +26157,7 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26022
26157
|
plan {
|
|
26023
26158
|
description
|
|
26024
26159
|
name
|
|
26160
|
+
pricingDescription
|
|
26025
26161
|
}
|
|
26026
26162
|
...PriceListCardPriceDescription_PriceListFragment
|
|
26027
26163
|
...PriceListCardPrice_PriceListFragment
|
|
@@ -26035,16 +26171,18 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26035
26171
|
PriceListCardPriceDescription_PriceListFragment,
|
|
26036
26172
|
]);
|
|
26037
26173
|
function AddonPlanRow({ addonPriceList: maskedAddonPriceList, selectedPriceList, onClickSelect, isPurchased, }) {
|
|
26038
|
-
var _a, _b, _c, _d, _e, _f;
|
|
26174
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
26039
26175
|
// Read fragments
|
|
26040
26176
|
const addonPriceList = readFragment(AddonPlanRow_PriceListFragment, maskedAddonPriceList);
|
|
26041
|
-
const { quote, setIsAddonPlanLoading } = react.useContext(QuoteContext);
|
|
26177
|
+
const { quote: maskedQuote, setIsAddonPlanLoading } = react.useContext(QuoteContext);
|
|
26178
|
+
const quote = readFragment(AddonPlanRow_QuoteFragment, maskedQuote);
|
|
26042
26179
|
const { shadow, isInPreviewMode } = react.useContext(SubscriptionsContext);
|
|
26043
26180
|
const { isPending, addedQuoteChange, addAddonQuoteChange, deleteQuoteChange } = useToggleAddonPlan(quote, addonPriceList.id, selectedPriceList, setIsAddonPlanLoading);
|
|
26044
26181
|
const activeCharge = (_a = getActivePlanPriceData(addonPriceList, selectedPriceList)) === null || _a === void 0 ? void 0 : _a.activeCharge;
|
|
26045
26182
|
// Derived state
|
|
26046
26183
|
const switchDisabled = isInPreviewMode || isPurchased;
|
|
26047
|
-
|
|
26184
|
+
const hasCustomPrice = ((_b = addonPriceList.plan) === null || _b === void 0 ? void 0 : _b.pricingDescription) != null;
|
|
26185
|
+
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
26186
|
if (checked) {
|
|
26049
26187
|
addAddonQuoteChange();
|
|
26050
26188
|
}
|
|
@@ -26068,7 +26206,7 @@ const AddonPlans_PlanFragment = t(`
|
|
|
26068
26206
|
}
|
|
26069
26207
|
`, [AddonPlanModal_PriceListFragment, AddonPlanRow_PriceListFragment]);
|
|
26070
26208
|
|
|
26071
|
-
const query = t(`
|
|
26209
|
+
const query$2 = t(`
|
|
26072
26210
|
query PriceList($id: ID!) {
|
|
26073
26211
|
priceList(id: $id) {
|
|
26074
26212
|
addonPlans {
|
|
@@ -26082,7 +26220,7 @@ const query = t(`
|
|
|
26082
26220
|
`, [AddonPlans_PlanFragment]);
|
|
26083
26221
|
const getAddonPlans = async ({ token, id, apiHost, }) => {
|
|
26084
26222
|
var _a;
|
|
26085
|
-
const response = await execute(query, { apiHost, token }, { id });
|
|
26223
|
+
const response = await execute(query$2, { apiHost, token }, { id });
|
|
26086
26224
|
const addonPlans = (_a = response === null || response === void 0 ? void 0 : response.priceList) === null || _a === void 0 ? void 0 : _a.addonPlans;
|
|
26087
26225
|
// for each addon plan, filter out the price lists that are not visible
|
|
26088
26226
|
const visibleAddonPlans = addonPlans === null || addonPlans === void 0 ? void 0 : addonPlans.map(addonPlan => {
|
|
@@ -26190,7 +26328,10 @@ const PriceListGrid = ({ availablePriceLists, priceListChangeOptions, priceListS
|
|
|
26190
26328
|
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
26329
|
};
|
|
26192
26330
|
|
|
26193
|
-
const createAvailableBillingPeriods = (priceLists, selectedProduct) => {
|
|
26331
|
+
const createAvailableBillingPeriods = (priceLists, selectedProduct, upgradingSubscription) => {
|
|
26332
|
+
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true) {
|
|
26333
|
+
return [upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.periodMonths];
|
|
26334
|
+
}
|
|
26194
26335
|
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
26336
|
};
|
|
26196
26337
|
const showInfoNotification$1 = common.useInfoNotification();
|
|
@@ -26204,11 +26345,18 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26204
26345
|
const [selectedBillingPeriod, setSelectedBillingPeriod] = react.useState(null);
|
|
26205
26346
|
const [priceListStart, setPriceListStart] = react.useState(0);
|
|
26206
26347
|
// 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]);
|
|
26348
|
+
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]);
|
|
26349
|
+
// TODO: clean up available pricelists calculation. We should calculate it once, not three times.
|
|
26350
|
+
const subscriptionIsAddon = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true;
|
|
26208
26351
|
const availablePriceLists = react.useMemo(() => {
|
|
26209
26352
|
var _a;
|
|
26210
|
-
|
|
26211
|
-
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id))
|
|
26353
|
+
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 &&
|
|
26354
|
+
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id));
|
|
26355
|
+
// If the subscription is an addon, we should only show its price lists because we don't support changing add-on plans.
|
|
26356
|
+
if (subscriptionIsAddon) {
|
|
26357
|
+
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))) || []);
|
|
26358
|
+
}
|
|
26359
|
+
return priceLists.filter(priceList => priceList.plan.addon !== true) || [];
|
|
26212
26360
|
}, [priceListChangeOptions, selectedBillingPeriod, selectedProduct]);
|
|
26213
26361
|
// Handlers
|
|
26214
26362
|
const onChangeBillingPeriod = react.useCallback((billingPeriod) => {
|
|
@@ -26237,7 +26385,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26237
26385
|
}
|
|
26238
26386
|
}, [selectedPriceList, priceListChangeOptions, upgradingSubscription]);
|
|
26239
26387
|
const onChangeProduct = react.useCallback((product) => {
|
|
26240
|
-
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product);
|
|
26388
|
+
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product, upgradingSubscription);
|
|
26241
26389
|
if (selectedBillingPeriod &&
|
|
26242
26390
|
!(newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods.includes(billingPeriodConverter(selectedBillingPeriod)))) {
|
|
26243
26391
|
onChangeBillingPeriod(periodMonthsConverter((newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods[0]) !== undefined ? newAvailableBillingPeriods[0] : 1));
|
|
@@ -26248,7 +26396,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26248
26396
|
const initialProduct = (_a = priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.products) === null || _a === void 0 ? void 0 : _a[0];
|
|
26249
26397
|
const initialBillingPeriod = react.useMemo(() => {
|
|
26250
26398
|
var _a, _b, _c;
|
|
26251
|
-
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct);
|
|
26399
|
+
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct, upgradingSubscription);
|
|
26252
26400
|
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
26401
|
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) &&
|
|
26254
26402
|
periodMonthsConverted &&
|
|
@@ -26904,80 +27052,177 @@ const PageSubTitle = ({ title }) => {
|
|
|
26904
27052
|
return (jsxRuntime.jsx("div", { className: "bunny-shrink-0", style: { color: secondaryColor }, children: title }));
|
|
26905
27053
|
};
|
|
26906
27054
|
|
|
26907
|
-
const
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
27055
|
+
const AccountContactsFragment = t(`
|
|
27056
|
+
fragment AccountContactsFragment on Contact {
|
|
27057
|
+
id
|
|
27058
|
+
email
|
|
27059
|
+
firstName
|
|
27060
|
+
}
|
|
27061
|
+
`, []);
|
|
27062
|
+
|
|
27063
|
+
const AddContactButton = ({ onClick }) => {
|
|
27064
|
+
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" }) }));
|
|
27065
|
+
};
|
|
27066
|
+
|
|
27067
|
+
const useSetAccountContactsQueryData = () => {
|
|
27068
|
+
const token = useToken();
|
|
27069
|
+
const queryClient = reactQuery.useQueryClient();
|
|
27070
|
+
const setAccountContactsQueryData = (accountId, updater) => {
|
|
27071
|
+
queryClient.setQueryData(QueryKeyFactory.accountContactsKey({ accountId, token }), updater);
|
|
27072
|
+
};
|
|
27073
|
+
return { setAccountContactsQueryData };
|
|
27074
|
+
};
|
|
27075
|
+
|
|
27076
|
+
const mutation$1 = t(`
|
|
27077
|
+
mutation ContactCreate($attributes: ContactAttributes!) {
|
|
27078
|
+
contactCreate(attributes: $attributes) {
|
|
27079
|
+
contact {
|
|
27080
|
+
id
|
|
27081
|
+
account {
|
|
27082
|
+
contacts {
|
|
27083
|
+
...AccountContactsFragment
|
|
27084
|
+
}
|
|
26917
27085
|
}
|
|
26918
|
-
billingCountry
|
|
26919
|
-
billingState
|
|
26920
|
-
billingStreet
|
|
26921
|
-
billingZip
|
|
26922
|
-
name
|
|
26923
|
-
taxNumber
|
|
26924
27086
|
}
|
|
26925
27087
|
errors
|
|
26926
27088
|
}
|
|
26927
|
-
|
|
26928
|
-
|
|
26929
|
-
const
|
|
26930
|
-
var _a;
|
|
26931
|
-
const
|
|
26932
|
-
|
|
26933
|
-
|
|
26934
|
-
|
|
26935
|
-
|
|
26936
|
-
|
|
27089
|
+
}
|
|
27090
|
+
`, [AccountContactsFragment]);
|
|
27091
|
+
const contactCreate = async ({ attributes, apiHost, token }) => {
|
|
27092
|
+
var _a, _b;
|
|
27093
|
+
const response = await execute(mutation$1, { apiHost, token }, { attributes });
|
|
27094
|
+
if ((_a = response.contactCreate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
27095
|
+
throw new Error(response.contactCreate.errors[0]);
|
|
27096
|
+
}
|
|
27097
|
+
return (_b = response.contactCreate) === null || _b === void 0 ? void 0 : _b.contact;
|
|
27098
|
+
};
|
|
27099
|
+
|
|
27100
|
+
const AddContactModal = ({ open, onClose, accountId, onContactCreated, }) => {
|
|
27101
|
+
const [form] = antd.Form.useForm();
|
|
27102
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
27103
|
+
const token = useToken();
|
|
27104
|
+
const showErrorNotification = common.useErrorNotification();
|
|
27105
|
+
const showSuccessNotification = common.useSuccessNotification();
|
|
27106
|
+
const { setAccountContactsQueryData } = useSetAccountContactsQueryData();
|
|
27107
|
+
const { mutate: createContact, isPending: isCreatingContact } = reactQuery.useMutation({
|
|
27108
|
+
mutationFn: (attributes) => contactCreate({ attributes, apiHost, token }),
|
|
27109
|
+
onSuccess: newContact => {
|
|
27110
|
+
var _a, _b;
|
|
27111
|
+
showSuccessNotification('Contact created successfully');
|
|
27112
|
+
// Add the new contact to the cache
|
|
27113
|
+
if (newContact && accountId) {
|
|
27114
|
+
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);
|
|
27115
|
+
}
|
|
27116
|
+
onClose();
|
|
27117
|
+
form.resetFields();
|
|
27118
|
+
const newContactData = newContact ? readFragment(AccountContactsFragment, newContact) : null;
|
|
27119
|
+
if (newContactData === null || newContactData === void 0 ? void 0 : newContactData.id) {
|
|
27120
|
+
onContactCreated === null || onContactCreated === void 0 ? void 0 : onContactCreated(newContactData.id);
|
|
27121
|
+
}
|
|
27122
|
+
},
|
|
26937
27123
|
});
|
|
26938
|
-
const
|
|
26939
|
-
|
|
26940
|
-
|
|
26941
|
-
|
|
27124
|
+
const handleAddContact = () => {
|
|
27125
|
+
if (!accountId) {
|
|
27126
|
+
showErrorNotification('Account ID is required to create a contact');
|
|
27127
|
+
return;
|
|
27128
|
+
}
|
|
27129
|
+
form.validateFields().then(values => {
|
|
27130
|
+
createContact({
|
|
27131
|
+
email: values.email || null,
|
|
27132
|
+
firstName: values.firstName || null,
|
|
27133
|
+
lastName: values.lastName || null,
|
|
27134
|
+
accountId: accountId,
|
|
27135
|
+
portalAccess: true,
|
|
27136
|
+
});
|
|
27137
|
+
});
|
|
27138
|
+
};
|
|
27139
|
+
return (jsxRuntime.jsx(antd.Modal, { title: "Add new contact", open: open, onCancel: () => {
|
|
27140
|
+
onClose();
|
|
27141
|
+
form.resetFields();
|
|
27142
|
+
}, footer: [
|
|
27143
|
+
jsxRuntime.jsx(antd.Button, { onClick: () => {
|
|
27144
|
+
onClose();
|
|
27145
|
+
form.resetFields();
|
|
27146
|
+
}, children: "Cancel" }, "cancel"),
|
|
27147
|
+
jsxRuntime.jsx(antd.Button, { type: "primary", loading: isCreatingContact, onClick: handleAddContact, children: "Add contact" }, "submit"),
|
|
27148
|
+
], 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: [
|
|
27149
|
+
{ required: true, message: 'Email is required' },
|
|
27150
|
+
{ type: 'email', message: 'Please enter a valid email' },
|
|
27151
|
+
], children: jsxRuntime.jsx(antd.Input, { placeholder: "Enter email" }) })] }) }));
|
|
26942
27152
|
};
|
|
26943
27153
|
|
|
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 {
|
|
27154
|
+
const BillingDetailsSection_AccountFragment = t(`
|
|
27155
|
+
fragment BillingDetailsSection_AccountFragment on Account {
|
|
26958
27156
|
id
|
|
27157
|
+
name
|
|
27158
|
+
billingStreet
|
|
27159
|
+
billingCity
|
|
27160
|
+
billingState
|
|
27161
|
+
billingZip
|
|
27162
|
+
billingCountry
|
|
27163
|
+
taxNumber
|
|
27164
|
+
billingContactId
|
|
27165
|
+
secondaryBillingContactIds
|
|
27166
|
+
billingContact {
|
|
27167
|
+
email
|
|
27168
|
+
firstName
|
|
27169
|
+
}
|
|
26959
27170
|
}
|
|
26960
|
-
|
|
26961
|
-
|
|
26962
|
-
const
|
|
27171
|
+
`, []);
|
|
27172
|
+
|
|
27173
|
+
const mutation = t(`
|
|
27174
|
+
mutation AccountUpdate($id: ID!, $attributes: AccountAttributes!) {
|
|
27175
|
+
accountUpdate(id: $id, attributes: $attributes) {
|
|
27176
|
+
account {
|
|
27177
|
+
...BillingDetailsSection_AccountFragment
|
|
27178
|
+
}
|
|
27179
|
+
errors
|
|
27180
|
+
}
|
|
27181
|
+
}
|
|
27182
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27183
|
+
const accountUpdate = async ({ accountId, attributes, apiHost, token, }) => {
|
|
26963
27184
|
var _a;
|
|
26964
|
-
const response = await
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
27185
|
+
const response = await execute(mutation, { apiHost, token }, { id: accountId, attributes });
|
|
27186
|
+
return (_a = response.accountUpdate) === null || _a === void 0 ? void 0 : _a.account;
|
|
27187
|
+
};
|
|
27188
|
+
|
|
27189
|
+
const query$1 = t(`
|
|
27190
|
+
query GetAccount($id: ID!) {
|
|
27191
|
+
account(id: $id) {
|
|
27192
|
+
...BillingDetailsSection_AccountFragment
|
|
27193
|
+
}
|
|
27194
|
+
}
|
|
27195
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27196
|
+
const getAccount = async ({ accountId, apiHost, token, }) => {
|
|
27197
|
+
const response = await execute(query$1, { apiHost, token }, { id: accountId });
|
|
27198
|
+
return response.account;
|
|
27199
|
+
};
|
|
27200
|
+
|
|
27201
|
+
const query = t(`
|
|
27202
|
+
query GetAccountContacts($accountId: ID!) {
|
|
27203
|
+
account(id: $accountId) {
|
|
27204
|
+
id
|
|
27205
|
+
contacts {
|
|
27206
|
+
...AccountContactsFragment
|
|
27207
|
+
}
|
|
27208
|
+
}
|
|
26971
27209
|
}
|
|
26972
|
-
|
|
27210
|
+
`, [AccountContactsFragment]);
|
|
27211
|
+
const getAccountContacts = async ({ accountId, apiHost, token, }) => {
|
|
27212
|
+
var _a;
|
|
27213
|
+
const response = await execute(query, { apiHost, token }, { accountId });
|
|
27214
|
+
return (_a = response.account) === null || _a === void 0 ? void 0 : _a.contacts;
|
|
26973
27215
|
};
|
|
26974
27216
|
|
|
26975
27217
|
const { Text } = antd.Typography;
|
|
26976
27218
|
function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
27219
|
+
var _a, _b, _c;
|
|
26977
27220
|
// State
|
|
26978
27221
|
const [isFormEdited, setIsFormEdited] = react.useState(false);
|
|
26979
27222
|
const [form] = antd.Form.useForm();
|
|
26980
27223
|
const values = antd.Form.useWatch([], form);
|
|
27224
|
+
const [isAddContactModalOpen, setIsAddContactModalOpen] = react.useState(false);
|
|
27225
|
+
const [contactFieldType, setContactFieldType] = react.useState(null);
|
|
26981
27226
|
// Context
|
|
26982
27227
|
const { apiHost } = react.useContext(BunnyContext);
|
|
26983
27228
|
const token = useToken();
|
|
@@ -26986,14 +27231,37 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
26986
27231
|
const queryClient = reactQuery.useQueryClient();
|
|
26987
27232
|
const showErrorNotification = common.useErrorNotification();
|
|
26988
27233
|
const showSuccessNotification = common.useSuccessNotification();
|
|
27234
|
+
const { currentUser } = useCurrentUserData(token);
|
|
27235
|
+
const accountId = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.account) === null || _a === void 0 ? void 0 : _a.id;
|
|
26989
27236
|
// Queries
|
|
26990
|
-
const { data:
|
|
26991
|
-
queryKey:
|
|
26992
|
-
queryFn: () =>
|
|
27237
|
+
const { data: maskedAccount, isLoading: isLoadingAccount } = reactQuery.useQuery({
|
|
27238
|
+
queryKey: QueryKeyFactory.accountBillingDetailsKey({ accountId, token }),
|
|
27239
|
+
queryFn: () => {
|
|
27240
|
+
if (!accountId) {
|
|
27241
|
+
throw new Error('Account ID is required');
|
|
27242
|
+
}
|
|
27243
|
+
return getAccount({ accountId, apiHost, token });
|
|
27244
|
+
},
|
|
27245
|
+
enabled: !!accountId,
|
|
27246
|
+
});
|
|
27247
|
+
const account = readFragment(BillingDetailsSection_AccountFragment, maskedAccount);
|
|
27248
|
+
const { data: contacts, isLoading: isLoadingContacts } = reactQuery.useQuery({
|
|
27249
|
+
queryKey: QueryKeyFactory.accountContactsKey({ accountId, token }),
|
|
27250
|
+
queryFn: () => {
|
|
27251
|
+
if (!accountId) {
|
|
27252
|
+
throw new Error('Account ID is required');
|
|
27253
|
+
}
|
|
27254
|
+
return getAccountContacts({ accountId, apiHost, token });
|
|
27255
|
+
},
|
|
27256
|
+
enabled: !!accountId,
|
|
26993
27257
|
});
|
|
26994
|
-
const { mutate:
|
|
27258
|
+
const { mutate: updateAccount, isPending: isUpdatingAccount } = reactQuery.useMutation({
|
|
26995
27259
|
mutationFn: async (changedFormData) => {
|
|
26996
|
-
|
|
27260
|
+
if (!accountId) {
|
|
27261
|
+
throw new Error('Account ID is required');
|
|
27262
|
+
}
|
|
27263
|
+
const updatedAccount = await accountUpdate({
|
|
27264
|
+
accountId,
|
|
26997
27265
|
attributes: {
|
|
26998
27266
|
name: changedFormData.name,
|
|
26999
27267
|
billingStreet: changedFormData.billingStreet,
|
|
@@ -27001,77 +27269,92 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
27001
27269
|
billingZip: changedFormData.billingZip,
|
|
27002
27270
|
billingState: changedFormData.billingState,
|
|
27003
27271
|
billingCountry: changedFormData.billingCountry,
|
|
27004
|
-
billingContactEmail: changedFormData.billingContactEmail,
|
|
27005
27272
|
taxNumber: changedFormData.taxNumber,
|
|
27273
|
+
billingContactId: changedFormData.billingContactId || null,
|
|
27274
|
+
secondaryBillingContactIds: Array.isArray(changedFormData.secondaryBillingContactIds)
|
|
27275
|
+
? changedFormData.secondaryBillingContactIds
|
|
27276
|
+
: null,
|
|
27006
27277
|
},
|
|
27007
27278
|
token,
|
|
27008
27279
|
apiHost,
|
|
27009
27280
|
});
|
|
27010
|
-
queryClient.setQueryData(
|
|
27011
|
-
|
|
27012
|
-
...old,
|
|
27013
|
-
...updatedBillingDetails.billingDetails,
|
|
27014
|
-
};
|
|
27015
|
-
});
|
|
27016
|
-
return updatedBillingDetails;
|
|
27281
|
+
queryClient.setQueryData(QueryKeyFactory.accountBillingDetailsKey({ accountId, token }), updatedAccount);
|
|
27282
|
+
return updatedAccount;
|
|
27017
27283
|
},
|
|
27018
27284
|
onSuccess: () => {
|
|
27019
27285
|
showSuccessNotification('Your account details have been saved');
|
|
27020
27286
|
queryClient.invalidateQueries({
|
|
27021
|
-
queryKey:
|
|
27287
|
+
queryKey: QueryKeyFactory.taxationRequiredAccountFieldsKey({
|
|
27022
27288
|
token,
|
|
27023
27289
|
}),
|
|
27024
27290
|
});
|
|
27025
27291
|
},
|
|
27026
27292
|
});
|
|
27027
|
-
// Set form values when
|
|
27293
|
+
// Set form values when account is loaded
|
|
27028
27294
|
react.useEffect(() => {
|
|
27029
|
-
|
|
27030
|
-
if (billingDetails) {
|
|
27295
|
+
if (account) {
|
|
27031
27296
|
form.setFieldsValue({
|
|
27032
|
-
billingStreet:
|
|
27033
|
-
billingCity:
|
|
27034
|
-
billingZip:
|
|
27035
|
-
billingState:
|
|
27036
|
-
billingCountry:
|
|
27037
|
-
|
|
27038
|
-
|
|
27297
|
+
billingStreet: account.billingStreet,
|
|
27298
|
+
billingCity: account.billingCity,
|
|
27299
|
+
billingZip: account.billingZip,
|
|
27300
|
+
billingState: account.billingState,
|
|
27301
|
+
billingCountry: account.billingCountry,
|
|
27302
|
+
billingContactId: account.billingContactId,
|
|
27303
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27304
|
+
taxNumber: account.taxNumber,
|
|
27039
27305
|
});
|
|
27040
27306
|
}
|
|
27041
|
-
}, [
|
|
27307
|
+
}, [account]);
|
|
27042
27308
|
react.useEffect(() => {
|
|
27043
27309
|
form.validateFields({ validateOnly: true });
|
|
27044
27310
|
const isFormEdited = () => {
|
|
27045
|
-
|
|
27046
|
-
if (!billingDetails)
|
|
27311
|
+
if (!account)
|
|
27047
27312
|
return false;
|
|
27048
27313
|
const currentValues = form.getFieldsValue();
|
|
27049
27314
|
const accountValues = {
|
|
27050
|
-
billingStreet:
|
|
27051
|
-
billingCity:
|
|
27052
|
-
billingZip:
|
|
27053
|
-
billingState:
|
|
27054
|
-
billingCountry:
|
|
27055
|
-
|
|
27056
|
-
|
|
27315
|
+
billingStreet: account.billingStreet,
|
|
27316
|
+
billingCity: account.billingCity,
|
|
27317
|
+
billingZip: account.billingZip,
|
|
27318
|
+
billingState: account.billingState,
|
|
27319
|
+
billingCountry: account.billingCountry,
|
|
27320
|
+
billingContactId: account.billingContactId,
|
|
27321
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27322
|
+
taxNumber: account.taxNumber,
|
|
27057
27323
|
};
|
|
27058
|
-
return Object.keys(
|
|
27324
|
+
return Object.keys(accountValues).some(key => {
|
|
27059
27325
|
const value = accountValues[key];
|
|
27060
|
-
|
|
27326
|
+
const currentValue = currentValues[key];
|
|
27327
|
+
// Handle array comparison for secondaryBillingContactIds
|
|
27328
|
+
if (Array.isArray(value) && Array.isArray(currentValue)) {
|
|
27329
|
+
return JSON.stringify(value === null || value === void 0 ? void 0 : value.sort()) !== JSON.stringify(currentValue === null || currentValue === void 0 ? void 0 : currentValue.sort());
|
|
27330
|
+
}
|
|
27331
|
+
return currentValue !== value;
|
|
27061
27332
|
});
|
|
27062
27333
|
};
|
|
27063
27334
|
setIsFormEdited(isFormEdited());
|
|
27064
|
-
}, [form, values,
|
|
27335
|
+
}, [form, values, account]);
|
|
27065
27336
|
// Validate form fields when isFormEdited changes
|
|
27066
27337
|
react.useEffect(() => {
|
|
27067
27338
|
const validateOnly = isFormEdited ? false : true;
|
|
27068
27339
|
form.validateFields({ validateOnly: validateOnly });
|
|
27069
27340
|
}, [isFormEdited]);
|
|
27341
|
+
const handleContactCreated = (contactId) => {
|
|
27342
|
+
if (contactFieldType === 'primary') {
|
|
27343
|
+
form.setFieldValue('billingContactId', contactId);
|
|
27344
|
+
}
|
|
27345
|
+
else if (contactFieldType === 'secondary') {
|
|
27346
|
+
const currentSecondaryContacts = form.getFieldValue('secondaryBillingContactIds') || [];
|
|
27347
|
+
if (!currentSecondaryContacts.includes(contactId)) {
|
|
27348
|
+
form.setFieldValue('secondaryBillingContactIds', [...currentSecondaryContacts, contactId]);
|
|
27349
|
+
}
|
|
27350
|
+
}
|
|
27351
|
+
setContactFieldType(null);
|
|
27352
|
+
};
|
|
27070
27353
|
const saveBillingDetails = async () => {
|
|
27071
27354
|
form.validateFields({ validateOnly: false }).then(async () => {
|
|
27072
27355
|
try {
|
|
27073
27356
|
await form.validateFields();
|
|
27074
|
-
|
|
27357
|
+
updateAccount(form.getFieldsValue());
|
|
27075
27358
|
}
|
|
27076
27359
|
catch (error) {
|
|
27077
27360
|
if (error instanceof Error) {
|
|
@@ -27089,21 +27372,38 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
27089
27372
|
const filteredCountryList = react.useMemo(() => {
|
|
27090
27373
|
return countryListFilter ? common.Lists.COUNTRY_LIST.filter(countryListFilter) : common.Lists.COUNTRY_LIST;
|
|
27091
27374
|
}, [countryListFilter]);
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
((
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27104
|
-
|
|
27105
|
-
|
|
27106
|
-
|
|
27375
|
+
const isLoading = isLoadingAccount || isLoadingContacts;
|
|
27376
|
+
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: [
|
|
27377
|
+
{
|
|
27378
|
+
required: false,
|
|
27379
|
+
},
|
|
27380
|
+
], 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) => {
|
|
27381
|
+
var _a, _b;
|
|
27382
|
+
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
27383
|
+
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
27384
|
+
} }) }) })] }), 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 => {
|
|
27385
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27386
|
+
return {
|
|
27387
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27388
|
+
? `${contactData.firstName}`
|
|
27389
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27390
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27391
|
+
};
|
|
27392
|
+
})) !== 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 => {
|
|
27393
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27394
|
+
return {
|
|
27395
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27396
|
+
? `${contactData.firstName}`
|
|
27397
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27398
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27399
|
+
};
|
|
27400
|
+
})) !== null && _c !== void 0 ? _c : [], popupRender: menu => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menu, jsxRuntime.jsx(AddContactButton, { onClick: () => {
|
|
27401
|
+
setContactFieldType('secondary');
|
|
27402
|
+
setIsAddContactModalOpen(true);
|
|
27403
|
+
} })] })) }) }), 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: () => {
|
|
27404
|
+
setIsAddContactModalOpen(false);
|
|
27405
|
+
setContactFieldType(null);
|
|
27406
|
+
}, accountId: accountId, onContactCreated: handleContactCreated })] }));
|
|
27107
27407
|
}
|
|
27108
27408
|
|
|
27109
27409
|
const BillingDetails = ({ className, countryListFilter, hideBillingDetailsForm = false, hidePaymentMethodForm = false, isCardEnabled = true, isUpgradeFromTrial = false, shadow = 'shadow-md', onSavePaymentMethod, }) => {
|