@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/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { isValidElement, createContext, useContext, useMemo, useState, useEffect, useRef, createElement, useCallback, Fragment as Fragment$1 } from 'react';
|
|
3
3
|
import { DownloadOutlined, CreditCardOutlined, EllipsisOutlined, BankOutlined, SearchOutlined, CloseOutlined, CheckCircleFilled, InfoCircleOutlined } from '@ant-design/icons';
|
|
4
|
-
import { useErrorNotification, DEFAULT_CONFIG, createClientDevHeaders as createClientDevHeaders$1, X_BUNNY_COMPONENTS_VERSION_HEADER_NAME, QueryKeyFactory as QueryKeyFactory$1, useIsMobile as useIsMobile$1, DEFAULT_BRAND_COLOR, isColorTooDark, DEFAULT_TOP_NAV_IMAGE_URL, DEFAULT_ACCENT_COLOR, INPUT_BORDER_COLOR, SLATE_50, SLATE_400, SLATE_200, DEFAULT_SECONDARY_COLOR, request as request$1, useAllErrorFormats as useAllErrorFormats$1, formatCurrency as formatCurrency$1, GRAY_500, GRAY_200, useSuccessNotification, PAYABLE_INVOICE_STATES, BreakpointNumbers as BreakpointNumbers$1, useGraphQLmutation, useInfoNotification, formatDate, TransactionState, SLATE_600, WHITE, TransactionKind, QuoteChangeKind, SLATE_500, PRIMARY_COLOR, Lists, getAccount
|
|
4
|
+
import { useErrorNotification, DEFAULT_CONFIG, createClientDevHeaders as createClientDevHeaders$1, X_BUNNY_COMPONENTS_VERSION_HEADER_NAME, QueryKeyFactory as QueryKeyFactory$1, useIsMobile as useIsMobile$1, DEFAULT_BRAND_COLOR, isColorTooDark, DEFAULT_TOP_NAV_IMAGE_URL, DEFAULT_ACCENT_COLOR, INPUT_BORDER_COLOR, SLATE_50, SLATE_400, SLATE_200, DEFAULT_SECONDARY_COLOR, request as request$1, useAllErrorFormats as useAllErrorFormats$1, formatCurrency as formatCurrency$1, GRAY_500, GRAY_200, useSuccessNotification, PAYABLE_INVOICE_STATES, BreakpointNumbers as BreakpointNumbers$1, useGraphQLmutation, useInfoNotification, formatDate, TransactionState, SLATE_600, WHITE, TransactionKind, QuoteChangeKind, ChargeType, PERIOD_LABELS, SLATE_500, PRIMARY_COLOR, Lists, getAccount as getAccount$1, MODAL_MAX_HEIGHT, DataInterval, SLATE_100 } from '@bunnyapp/common';
|
|
5
5
|
import { ConfigProvider, Spin, Typography, Button, theme as theme$1, Tag, Dropdown, Input, Modal, Checkbox, Skeleton, Collapse, Form, Tooltip, Drawer, Card as Card$1, Select, Divider, Popconfirm, Table, Radio, Space, Switch } from 'antd';
|
|
6
6
|
import { Markup } from 'interweave';
|
|
7
7
|
import request from 'graphql-request';
|
|
@@ -46,7 +46,7 @@ function styleInject(css, ref) {
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
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";
|
|
49
|
+
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";
|
|
50
50
|
styleInject(css_248z);
|
|
51
51
|
|
|
52
52
|
const IGNORE_ERRORS = ['Invalid or missing authorization', '["Not found"]'];
|
|
@@ -141,7 +141,7 @@ const useAllErrorFormats = () => {
|
|
|
141
141
|
};
|
|
142
142
|
|
|
143
143
|
// This will be replaced at build time by rollup-plugin-replace
|
|
144
|
-
const PACKAGE_VERSION = '1.
|
|
144
|
+
const PACKAGE_VERSION = '1.7.0-beta.1';
|
|
145
145
|
const createRequestHeaders = (token) => {
|
|
146
146
|
const headers = createClientDevHeaders({ token });
|
|
147
147
|
// Add the components version header
|
|
@@ -927,7 +927,7 @@ function readFragment(...r) {
|
|
|
927
927
|
|
|
928
928
|
var t = initGraphQLTada();
|
|
929
929
|
|
|
930
|
-
const query$
|
|
930
|
+
const query$9 = t(`
|
|
931
931
|
query entityBranding {
|
|
932
932
|
entityBranding {
|
|
933
933
|
accentColor
|
|
@@ -937,7 +937,7 @@ const query$7 = t(`
|
|
|
937
937
|
}
|
|
938
938
|
`);
|
|
939
939
|
const getBranding = async ({ token, apiHost }) => {
|
|
940
|
-
return await execute(query$
|
|
940
|
+
return await execute(query$9, { apiHost, token }, {});
|
|
941
941
|
};
|
|
942
942
|
|
|
943
943
|
const BunnyContext = createContext({});
|
|
@@ -1141,10 +1141,10 @@ const DocumentTemplatePreview = ({ targetUrl }) => {
|
|
|
1141
1141
|
}, children: jsx(RPPages, {}) }))] }) }) }));
|
|
1142
1142
|
};
|
|
1143
1143
|
|
|
1144
|
-
const { Text: Text$
|
|
1144
|
+
const { Text: Text$B } = Typography;
|
|
1145
1145
|
function BackButton({ onClick, title }) {
|
|
1146
1146
|
const { brandColor } = useBrand();
|
|
1147
|
-
return (jsxs(StyledBackButton, { brandColor: brandColor, className: "bunny-flex bunny-items-center bunny-gap-2 bunny-p-0 bunny-text-gray-400", onClick: onClick, children: [jsx(FontAwesomeIcon, { className: "pt-0.5", icon: faArrowLeft }), jsx(Text$
|
|
1147
|
+
return (jsxs(StyledBackButton, { brandColor: brandColor, className: "bunny-flex bunny-items-center bunny-gap-2 bunny-p-0 bunny-text-gray-400", onClick: onClick, children: [jsx(FontAwesomeIcon, { className: "pt-0.5", icon: faArrowLeft }), jsx(Text$B, { className: "bunny-text-sm bunny-text-gray-400 bunny-text-nowrap", children: title || 'back' })] }));
|
|
1148
1148
|
}
|
|
1149
1149
|
const StyledBackButton = styled.button.withConfig({
|
|
1150
1150
|
shouldForwardProp: prop => !['brandColor'].includes(prop),
|
|
@@ -1180,7 +1180,7 @@ const InvoiceQuoteView = ({ children, formattedInvoice, html, backButtonName, on
|
|
|
1180
1180
|
}, children: [targetUrl ? (jsx(DocumentTemplatePreview, { targetUrl: targetUrl })) : (jsx(Markup, { content: html })), children] }))] }));
|
|
1181
1181
|
};
|
|
1182
1182
|
|
|
1183
|
-
const MUTATION$
|
|
1183
|
+
const MUTATION$8 = `
|
|
1184
1184
|
query FormattedInvoice($id: ID) {
|
|
1185
1185
|
formattedInvoice(id: $id) {
|
|
1186
1186
|
amount
|
|
@@ -1248,7 +1248,7 @@ query FormattedInvoice($id: ID) {
|
|
|
1248
1248
|
const getFormattedInvoice = async ({ id, token, apiHost, }) => {
|
|
1249
1249
|
const vars = { id };
|
|
1250
1250
|
const response = await gqlRequest({
|
|
1251
|
-
query: MUTATION$
|
|
1251
|
+
query: MUTATION$8,
|
|
1252
1252
|
token,
|
|
1253
1253
|
vars,
|
|
1254
1254
|
apiHost,
|
|
@@ -18614,7 +18614,7 @@ function CardImage({ paymentMethod: maskedPaymentMethod, }) {
|
|
|
18614
18614
|
}
|
|
18615
18615
|
}
|
|
18616
18616
|
|
|
18617
|
-
const { Text: Text$
|
|
18617
|
+
const { Text: Text$A } = Typography;
|
|
18618
18618
|
const MiniCreditCard_PaymentMethodFragment = t(`
|
|
18619
18619
|
fragment MiniCreditCard_PaymentMethodFragment on PaymentMethod {
|
|
18620
18620
|
...CardImage_PaymentMethodFragment
|
|
@@ -18640,22 +18640,22 @@ function MiniCreditCard({ className, buttons, hideDropdownMenu = false, hideDefa
|
|
|
18640
18640
|
return darkMode ? 'var(--row-background-alternate)' : 'bg-slate-50';
|
|
18641
18641
|
}, [darkMode]);
|
|
18642
18642
|
const isDefault = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.isDefault;
|
|
18643
|
-
return (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 ? (jsxs(Fragment, { children: [jsx("div", { className: "bunny-flex bunny-flex-row bunny-gap-4", children: jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2 bunny-space-between bunny-w-full", children: [jsx(CardImage, { paymentMethod: paymentMethod }), jsx(Issuer, { issuer: (_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.issuer }), 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 && (jsx("div", { children: isDefault ? (jsx(Tag, { bordered: false, style: { color: brandColor, backgroundColor: `${brandColor}30` }, children: "Default" })) : null }))] }) }), buttons ? (buttons) : (jsx(Fragment, { children: !hideDropdownMenu && (jsx(DropdownMenu, { setDefault: onClickSetDefault, remove: onClickRemove, isDefault: isDefault !== null && isDefault !== void 0 ? isDefault : false, id: `credit-card-dropdown-${paymentMethod.id}` })) }))] })) : (jsxs("div", { className: "bunny-flex bunny-flex-row bunny-items-center justify-between w-full", children: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx(CreditCardOutlined, {}), jsx(Text$
|
|
18643
|
+
return (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 ? (jsxs(Fragment, { children: [jsx("div", { className: "bunny-flex bunny-flex-row bunny-gap-4", children: jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2 bunny-space-between bunny-w-full", children: [jsx(CardImage, { paymentMethod: paymentMethod }), jsx(Issuer, { issuer: (_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.issuer }), 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 && (jsx("div", { children: isDefault ? (jsx(Tag, { bordered: false, style: { color: brandColor, backgroundColor: `${brandColor}30` }, children: "Default" })) : null }))] }) }), buttons ? (buttons) : (jsx(Fragment, { children: !hideDropdownMenu && (jsx(DropdownMenu, { setDefault: onClickSetDefault, remove: onClickRemove, isDefault: isDefault !== null && isDefault !== void 0 ? isDefault : false, id: `credit-card-dropdown-${paymentMethod.id}` })) }))] })) : (jsxs("div", { className: "bunny-flex bunny-flex-row bunny-items-center justify-between w-full", children: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx(CreditCardOutlined, {}), jsx(Text$A, { className: "bunny-text-slate-400 bunny-text-sm", children: "No payment methods" })] }), jsx(Button, { disabled: true, type: "link" }), buttons] })) }));
|
|
18644
18644
|
}
|
|
18645
18645
|
const Identifier = ({ type, identifier, }) => {
|
|
18646
18646
|
if (type === 'link') {
|
|
18647
18647
|
return null;
|
|
18648
18648
|
}
|
|
18649
18649
|
if (type === 'cashapp') {
|
|
18650
|
-
return jsx(Text$
|
|
18650
|
+
return jsx(Text$A, { children: "Cashapp" });
|
|
18651
18651
|
}
|
|
18652
|
-
return (jsxs("div", { children: [jsx(Text$
|
|
18652
|
+
return (jsxs("div", { children: [jsx(Text$A, { className: "relative -top-0.5", children: "****" }), jsx(Text$A, { children: identifier })] }));
|
|
18653
18653
|
};
|
|
18654
18654
|
const Issuer = ({ issuer }) => {
|
|
18655
18655
|
const list = ['visa', 'link', 'jcb', 'discover', 'sepa'];
|
|
18656
18656
|
if (!issuer || issuer.length == 0 || list.includes(issuer === null || issuer === void 0 ? void 0 : issuer.toLowerCase()))
|
|
18657
18657
|
return null;
|
|
18658
|
-
return jsx(Text$
|
|
18658
|
+
return jsx(Text$A, { children: lodashExports.capitalize(issuer) });
|
|
18659
18659
|
};
|
|
18660
18660
|
const DropdownMenu = ({ setDefault, remove, isDefault, id, }) => {
|
|
18661
18661
|
const { brandColor } = useBrand();
|
|
@@ -18700,6 +18700,16 @@ const QueryKeyFactory = {
|
|
|
18700
18700
|
...(entityId ? [entityId] : []),
|
|
18701
18701
|
...(token ? [token] : []),
|
|
18702
18702
|
],
|
|
18703
|
+
accountBillingDetailsKey: ({ accountId, token }) => [
|
|
18704
|
+
'accountBillingDetails',
|
|
18705
|
+
...(accountId ? [accountId] : []),
|
|
18706
|
+
...(token ? [token] : []),
|
|
18707
|
+
],
|
|
18708
|
+
accountContactsKey: ({ accountId, token }) => [
|
|
18709
|
+
'accountContacts',
|
|
18710
|
+
...(accountId ? [accountId] : []),
|
|
18711
|
+
...(token ? [token] : []),
|
|
18712
|
+
],
|
|
18703
18713
|
brandingKey: (token) => ['branding', ...(token ? [token] : [])],
|
|
18704
18714
|
calculatedPricesKey: ({ priceListId, quantity, token }) => [
|
|
18705
18715
|
'calculatedPrices',
|
|
@@ -18766,7 +18776,7 @@ const QueryKeyFactory = {
|
|
|
18766
18776
|
paymentPluginsKey: (token) => ['paymentPlugins', ...(token ? [token] : [])],
|
|
18767
18777
|
};
|
|
18768
18778
|
|
|
18769
|
-
const query$
|
|
18779
|
+
const query$8 = t(`
|
|
18770
18780
|
query PaymentMethods($accountId: ID) {
|
|
18771
18781
|
paymentMethods(accountId: $accountId) {
|
|
18772
18782
|
nodes {
|
|
@@ -18795,7 +18805,7 @@ const query$6 = t(`
|
|
|
18795
18805
|
`, [PaymentForm_PaymentMethodsFragment]);
|
|
18796
18806
|
const getPaymentMethods = async ({ apiHost, token, accountId, }) => {
|
|
18797
18807
|
var _a, _b, _c;
|
|
18798
|
-
const response = await execute(query$
|
|
18808
|
+
const response = await execute(query$8, { apiHost, token }, { accountId });
|
|
18799
18809
|
// Filter out null values that are technically possible due to api schema
|
|
18800
18810
|
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 : [];
|
|
18801
18811
|
};
|
|
@@ -18820,7 +18830,7 @@ const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
|
18820
18830
|
};
|
|
18821
18831
|
};
|
|
18822
18832
|
|
|
18823
|
-
const mutation$
|
|
18833
|
+
const mutation$d = t(`
|
|
18824
18834
|
query PaymentPlugins($accountId: ID) {
|
|
18825
18835
|
paymentPlugins(accountId: $accountId) {
|
|
18826
18836
|
enabled
|
|
@@ -18848,7 +18858,7 @@ const mutation$5 = t(`
|
|
|
18848
18858
|
// }[];
|
|
18849
18859
|
// };
|
|
18850
18860
|
const getPaymentPlugins = async ({ apiHost, token, accountId, }) => {
|
|
18851
|
-
const response = await execute(mutation$
|
|
18861
|
+
const response = await execute(mutation$d, { apiHost, token }, { accountId });
|
|
18852
18862
|
return response === null || response === void 0 ? void 0 : response.paymentPlugins;
|
|
18853
18863
|
};
|
|
18854
18864
|
const usePaymentPlugins = (accountId) => {
|
|
@@ -19072,7 +19082,7 @@ function useSave$1({ onSaveSuccess, onSaveError, accountId, }) {
|
|
|
19072
19082
|
return { save, isSaving };
|
|
19073
19083
|
}
|
|
19074
19084
|
|
|
19075
|
-
const MUTATION$
|
|
19085
|
+
const MUTATION$7 = `
|
|
19076
19086
|
mutation checkout(
|
|
19077
19087
|
$invoiceId: ID,
|
|
19078
19088
|
$quoteId: ID,
|
|
@@ -19121,7 +19131,7 @@ const checkout = async ({ quoteId, invoiceId, paymentMethodId, paymentMethodData
|
|
|
19121
19131
|
};
|
|
19122
19132
|
}
|
|
19123
19133
|
const response = await gqlRequest({
|
|
19124
|
-
query: MUTATION$
|
|
19134
|
+
query: MUTATION$7,
|
|
19125
19135
|
token,
|
|
19126
19136
|
vars: mutationVars,
|
|
19127
19137
|
apiHost: apiHost,
|
|
@@ -19838,7 +19848,7 @@ const DemoPayExpiry = ({ autoFocus, onChange, placeholder, value, }) => {
|
|
|
19838
19848
|
return (jsx("div", { className: "bunny-grow", children: jsx(Input, { name: "expiry", autoFocus: autoFocus, onKeyDown: onKeyPress, onKeyUp: onKeyPress, onChange: onNumberChange, value: formatCardExpiry(value), maxLength: 5, placeholder: placeholder || "MM/YY" }) }));
|
|
19839
19849
|
};
|
|
19840
19850
|
|
|
19841
|
-
const { Text: Text$
|
|
19851
|
+
const { Text: Text$z } = Typography;
|
|
19842
19852
|
const handleAllErrorFormats = useAllErrorFormats$1();
|
|
19843
19853
|
const TEST_CARD = '4242424242424242';
|
|
19844
19854
|
const DemoPayForm = () => {
|
|
@@ -19878,7 +19888,7 @@ const DemoPayForm = () => {
|
|
|
19878
19888
|
const onCardCvcChange = (cvc) => {
|
|
19879
19889
|
setCardDetails({ ...cardDetails, cvc });
|
|
19880
19890
|
};
|
|
19881
|
-
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsx(Text$
|
|
19891
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsx(Text$z, { children: "DemoPay is for testing only." }), jsx(PaymentMethodFooter, { onSubmit: onSubmit })] }));
|
|
19882
19892
|
};
|
|
19883
19893
|
const StyledInputs = defaultStyled.div `
|
|
19884
19894
|
.ant-input {
|
|
@@ -19927,7 +19937,7 @@ const CardIcon = ({ className }) => {
|
|
|
19927
19937
|
return (jsxs("svg", { className: className, width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [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: SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M1.5 7.5H16.5", stroke: SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
19928
19938
|
};
|
|
19929
19939
|
|
|
19930
|
-
const { Text: Text$
|
|
19940
|
+
const { Text: Text$y } = Typography;
|
|
19931
19941
|
const PaymentMethodSelector = () => {
|
|
19932
19942
|
const accountId = useAccountId();
|
|
19933
19943
|
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
@@ -19941,7 +19951,7 @@ const PaymentOption = ({ selected, paymentPluginId, onClick, name, }) => {
|
|
|
19941
19951
|
const isCard = name === null || name === void 0 ? void 0 : name.toLowerCase().includes('card');
|
|
19942
19952
|
return (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
|
|
19943
19953
|
? `var(--row-background-dark) border-gray-500`
|
|
19944
|
-
: 'bunny-bg-slate-50 bunny-border-slate-200'} bunny-border`, onClick: () => onClick(paymentPluginId), children: [jsxs("div", { className: "bunny-flex bunny-gap-2 bunny-items-center bunny-pl-4", children: [jsx(Checkbox, { checked: selected, className: darkMode ? 'border-gray-400' : '' }), jsx(Text$
|
|
19954
|
+
: 'bunny-bg-slate-50 bunny-border-slate-200'} bunny-border`, onClick: () => onClick(paymentPluginId), children: [jsxs("div", { className: "bunny-flex bunny-gap-2 bunny-items-center bunny-pl-4", children: [jsx(Checkbox, { checked: selected, className: darkMode ? 'border-gray-400' : '' }), jsx(Text$y, { children: name })] }), isAch ? (jsx(BankOutlined, { className: "bunny-pr-4" })) : isCard ? (jsx(CardIcon, { className: "bunny-pr-4" })) : (jsx(CardIcon, { className: "bunny-pr-4" }))] }));
|
|
19945
19955
|
};
|
|
19946
19956
|
const PaymentOptionContainer = defaultStyled.div `
|
|
19947
19957
|
transition: border 0.3s ease;
|
|
@@ -19999,7 +20009,7 @@ const useAutoSetDefaultPaymentMethod = ({ handleSetDefault, setDefaultPaymentMet
|
|
|
19999
20009
|
]);
|
|
20000
20010
|
};
|
|
20001
20011
|
|
|
20002
|
-
const query$
|
|
20012
|
+
const query$7 = t(`
|
|
20003
20013
|
query GetCurrentUserData {
|
|
20004
20014
|
company {
|
|
20005
20015
|
name
|
|
@@ -20022,7 +20032,7 @@ const query$5 = t(`
|
|
|
20022
20032
|
`);
|
|
20023
20033
|
const getCurrentUserData = async ({ token, apiHost }) => {
|
|
20024
20034
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
20025
|
-
const response = await execute(query$
|
|
20035
|
+
const response = await execute(query$7, { apiHost, token }, {});
|
|
20026
20036
|
return {
|
|
20027
20037
|
authObjectName: (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.authObjectName,
|
|
20028
20038
|
account: (_b = response === null || response === void 0 ? void 0 : response.currentUser) === null || _b === void 0 ? void 0 : _b.account,
|
|
@@ -20190,6 +20200,8 @@ function PaymentFormContent({ onRemovePaymentMethod, onSetDefaultPaymentMethod,
|
|
|
20190
20200
|
const { paymentMethods: maskedPaymentMethods, isLoading: isPaymentMethodLoading } = usePaymentMethod({ accountId });
|
|
20191
20201
|
// Read fragments
|
|
20192
20202
|
const paymentMethods = useMemo(() => maskedPaymentMethods === null || maskedPaymentMethods === void 0 ? void 0 : maskedPaymentMethods.map(paymentMethod => readFragment(PaymentForm_PaymentMethodsFragment, paymentMethod)), [maskedPaymentMethods]);
|
|
20203
|
+
// Derived state
|
|
20204
|
+
const hasPaymentMethods = (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) && (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) > 0;
|
|
20193
20205
|
// Custom hooks
|
|
20194
20206
|
const { setDefaultPaymentMethod: handleSetDefault, loading: setDefaultPaymentMethodLoading } = useSetDefaultPaymentMethod(message => {
|
|
20195
20207
|
showErrorNotification$4(message, 'Error setting default payment method');
|
|
@@ -20228,7 +20240,7 @@ function PaymentFormContent({ onRemovePaymentMethod, onSetDefaultPaymentMethod,
|
|
|
20228
20240
|
label: !showPaymentMethodForm ? (jsx("div", { className: "bunny-pt-2", children: jsx(Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
|
|
20229
20241
|
children: (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsx(PaymentMethodSelector, {}), selectedPlugin && (jsx("div", { className: "bunny-flex bunny-flex-col", children: jsx(PaymentMethodDetails, {}) }))] })),
|
|
20230
20242
|
},
|
|
20231
|
-
] }), formattedAmountDue !== undefined && !showPaymentMethodForm && (jsx("div", { className: "bunny-px-4", children: jsx(CheckoutFooter, {}) }))] })) : (jsx(Button, { style: { margin: '0 16px' }, loading: isPaying, onClick: () => onPaymentFormSubmit(), type: "primary", children: isPaying ? 'Processing...' : 'Complete Order' })) }));
|
|
20243
|
+
] }), formattedAmountDue !== undefined && !showPaymentMethodForm && hasPaymentMethods ? (jsx("div", { className: "bunny-px-4", children: jsx(CheckoutFooter, {}) })) : null] })) : (jsx(Button, { style: { margin: '0 16px' }, loading: isPaying, onClick: () => onPaymentFormSubmit(), type: "primary", children: isPaying ? 'Processing...' : 'Complete Order' })) }));
|
|
20232
20244
|
}
|
|
20233
20245
|
|
|
20234
20246
|
function Invoice({ id, invoiceQuoteViewComponent, backButtonName, onBackButtonClick, onInvoiceDownloadError, onPaymentSuccess, shadow = 'shadow-md', className, hideDownloadButton = false, hidePaymentForm = false, onInvoiceLoaded, }) {
|
|
@@ -20286,7 +20298,7 @@ function ActualInvoice({ hidePaymentForm }) {
|
|
|
20286
20298
|
return (jsx("div", { className: "bunny-invoice-container", children: jsxs("div", { className: `bunny-flex bunny-gap-6 ${isMobile ? 'bunny-flex-col bunny-w-full' : ''} ${className}`, children: [formattedInvoice.isLegacy ? (jsx("div", { className: "bunny-flex bunny-justify-center bunny-w-full", children: jsx(LegacyDocument, { documentUuid: formattedInvoice.uuid, documentType: "invoice" }) })) : (invoiceQuoteViewComponent || (jsx(InvoiceQuoteView, { html: formattedInvoice.html, formattedInvoice: formattedInvoice, backButtonName: backButtonName, onBackButtonClick: onBackButtonClick }))), isInvoicePayable && !hidePaymentForm && (jsx("div", { className: `bunny-w-full ${hideDownloadButton || formattedInvoice.isLegacy ? '' : 'pt-12'}`, children: jsx(PaymentForm, { onPaymentSuccess: handlePaymentSuccess, invoice: formattedInvoice }) }))] }) }));
|
|
20287
20299
|
}
|
|
20288
20300
|
|
|
20289
|
-
const query$
|
|
20301
|
+
const query$6 = t(`
|
|
20290
20302
|
query formattedQuote($id: ID) {
|
|
20291
20303
|
formattedQuote(id: $id) {
|
|
20292
20304
|
quote {
|
|
@@ -20430,7 +20442,7 @@ const query$4 = t(`
|
|
|
20430
20442
|
}
|
|
20431
20443
|
`);
|
|
20432
20444
|
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
20433
|
-
const response = await execute(query$
|
|
20445
|
+
const response = await execute(query$6, { apiHost, token }, { id });
|
|
20434
20446
|
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
20435
20447
|
};
|
|
20436
20448
|
|
|
@@ -20766,14 +20778,14 @@ const AcceptQuoteModal = ({ acceptBoxVisible, formattedQuote, sendAccept, setAcc
|
|
|
20766
20778
|
}, open: acceptBoxVisible, title: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length) ? 'Start signing' : 'Accept quote', width: 400, children: jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", children: [jsx(Form.Item, { label: "Your name", name: "name", rules: createRules(true, 'Your name'), children: jsx(Input, { autoFocus: true, ref: firstInputRef }) }), jsx(Form.Item, { label: "Your job title", name: "title", rules: createRules(true, 'Your job title'), children: jsx(Input, {}) }), jsx(Form.Item, { label: "Purchase order number", name: "poNumber", rules: createRules(poNumberRequired, 'Purchase order number'), children: jsx(Input, {}) }), taxNumberRequired && (jsx(Form.Item, { name: "taxNumber", label: taxNumberLabel, rules: createRules(taxNumberRequired, taxNumberLabel), children: jsx(Input, {}) }))] }) }));
|
|
20767
20779
|
};
|
|
20768
20780
|
|
|
20769
|
-
const { Title: Title$2, Text: Text$
|
|
20781
|
+
const { Title: Title$2, Text: Text$x } = Typography;
|
|
20770
20782
|
const showSuccessNotification$2 = useSuccessNotification();
|
|
20771
20783
|
const PaymentHoldModal = ({ visible, setVisible, quote, }) => {
|
|
20772
20784
|
const queryClient = useQueryClient();
|
|
20773
20785
|
const token = useToken();
|
|
20774
20786
|
return (jsxs(StyledModal$2, { centered: true, onCancel: () => {
|
|
20775
20787
|
setVisible(false);
|
|
20776
|
-
}, footer: null, open: visible, width: 600, children: [jsxs("div", { className: "bunny-mt-5 bunny-pb-4 bunny-mx-4", children: [jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxs(Text$
|
|
20788
|
+
}, footer: null, open: visible, width: 600, children: [jsxs("div", { className: "bunny-mt-5 bunny-pb-4 bunny-mx-4", children: [jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), 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", ' ', formatCurrency$1(quote.amount, quote.currency), ". This amount will be charged to your payment method once the quote is signed."] })] }), jsx("div", { className: "bunny-mb-3", children: jsx(PaymentForm, { quote: {
|
|
20777
20789
|
amount: quote.amount,
|
|
20778
20790
|
currencyId: quote.currency,
|
|
20779
20791
|
id: quote.quote.id,
|
|
@@ -20823,7 +20835,7 @@ const StyledModal$2 = (props) => {
|
|
|
20823
20835
|
return jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
20824
20836
|
};
|
|
20825
20837
|
|
|
20826
|
-
const { Text: Text$
|
|
20838
|
+
const { Text: Text$w } = Typography;
|
|
20827
20839
|
defaultStyled.div `
|
|
20828
20840
|
Text {
|
|
20829
20841
|
width: 100%;
|
|
@@ -20915,7 +20927,7 @@ function QuoteButtons({ isAccepted, formattedQuote, isMobile, hideDownloadButton
|
|
|
20915
20927
|
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
20916
20928
|
return (jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
20917
20929
|
color: secondaryColor,
|
|
20918
|
-
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$
|
|
20930
|
+
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$w, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsx(Button, { icon: jsx(DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsx(Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", children: "Pay and sign" })) : (jsx(Fragment, { children: !isAccepted ? (jsx(Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
20919
20931
|
? 'Quote is expired'
|
|
20920
20932
|
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
20921
20933
|
? 'Start signing'
|
|
@@ -21036,9 +21048,9 @@ const getColor = (state) => {
|
|
|
21036
21048
|
}
|
|
21037
21049
|
};
|
|
21038
21050
|
|
|
21039
|
-
const { Text: Text$
|
|
21051
|
+
const { Text: Text$v } = Typography;
|
|
21040
21052
|
const TransactionDate = ({ date }) => {
|
|
21041
|
-
return jsx(Text$
|
|
21053
|
+
return jsx(Text$v, { className: "bunny-text-sm", children: formatDate(date) });
|
|
21042
21054
|
};
|
|
21043
21055
|
|
|
21044
21056
|
const ArrowDownToLine = ({ className, color = SLATE_600, }) => {
|
|
@@ -21082,13 +21094,13 @@ const TransactionGridCell = defaultStyled.div.withConfig({
|
|
|
21082
21094
|
min-width: 48px;
|
|
21083
21095
|
`;
|
|
21084
21096
|
|
|
21085
|
-
const { Text: Text$
|
|
21097
|
+
const { Text: Text$u } = Typography;
|
|
21086
21098
|
const TransactionsEmptyState = () => {
|
|
21087
21099
|
const { noTransactionsMessage } = useContext(TransactionsListContext);
|
|
21088
|
-
return (jsx(Text$
|
|
21100
|
+
return (jsx(Text$u, { className: "bunny-flex bunny-justify-center bunny-p-4 bunny-text-base", children: noTransactionsMessage || 'There are no transactions' }));
|
|
21089
21101
|
};
|
|
21090
21102
|
|
|
21091
|
-
const { Text: Text$
|
|
21103
|
+
const { Text: Text$t } = Typography;
|
|
21092
21104
|
const isInvoice = (transaction) => {
|
|
21093
21105
|
return transaction.kind === 'INVOICE';
|
|
21094
21106
|
};
|
|
@@ -21096,7 +21108,7 @@ const TransactionRowTitle = ({ transaction }) => {
|
|
|
21096
21108
|
if (!isInvoice(transaction)) {
|
|
21097
21109
|
return jsx(Fragment, {});
|
|
21098
21110
|
}
|
|
21099
|
-
return (jsx(Text$
|
|
21111
|
+
return (jsx(Text$t, { className: "bunny-text-slate-400", style: { fontSize: '11px' }, children: transaction.transactionable.number }));
|
|
21100
21112
|
};
|
|
21101
21113
|
|
|
21102
21114
|
function transactionDateToDisplay(transaction, transactionDateType) {
|
|
@@ -21114,7 +21126,7 @@ function transactionDateToDisplay(transaction, transactionDateType) {
|
|
|
21114
21126
|
}
|
|
21115
21127
|
}
|
|
21116
21128
|
|
|
21117
|
-
const { Text: Text$
|
|
21129
|
+
const { Text: Text$s } = Typography;
|
|
21118
21130
|
const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
21119
21131
|
const { columns, transactionDateType } = useContext(TransactionsListContext);
|
|
21120
21132
|
const { apiHost, darkMode } = useContext(BunnyContext);
|
|
@@ -21142,11 +21154,11 @@ const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
|
21142
21154
|
!showState &&
|
|
21143
21155
|
!showAmount &&
|
|
21144
21156
|
!showDownload &&
|
|
21145
|
-
!showAccountName && (jsx(TransactionGridCell, { children: jsx(Text$
|
|
21157
|
+
!showAccountName && (jsx(TransactionGridCell, { children: jsx(Text$s, { children: "No columns selected" }) })), showDate && (jsx(TransactionGridCell, { right: false, children: jsx(TransactionDate, { date: transactionDateToDisplay(transaction, transactionDateType) }) })), showTitle && (jsx(Fragment, { children: jsxs(TransactionGridCell, { right: false, className: "bunny-flex bunny-items-center bunny-gap-2", children: [jsx(Text$s, { children: lodashExports.capitalize(transaction.kind.toLowerCase()) }), jsx(TransactionRowTitle, { transaction: transaction })] }) })), showAccountName && (jsx(TransactionGridCell, { right: false, children: jsx(Text$s, { children: (_a = transaction.account) === null || _a === void 0 ? void 0 : _a.name }) })), !showDate && !showTitle && !showAccountName && jsx(TransactionGridCell, { right: false }), showDownload && (jsx(TransactionGridCell, { children: jsx(TransactionDownload, { transaction: transaction, token: token, apiHost: apiHost }) })), showState ? (jsx(TransactionGridCell, { right: false, children: jsx(StateTag, { state: transaction.state }) })) : null, showAmount && (jsx(TransactionGridCell, { right: true, children: jsx(Text$s, { children: formatCurrency$1(((_b = transaction === null || transaction === void 0 ? void 0 : transaction.transactionable) === null || _b === void 0 ? void 0 : _b.amount) || transaction.amount, transaction.currencyId) }) }))] }, index));
|
|
21146
21158
|
}) }));
|
|
21147
21159
|
};
|
|
21148
21160
|
|
|
21149
|
-
const { Text: Text$
|
|
21161
|
+
const { Text: Text$r } = Typography;
|
|
21150
21162
|
const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
21151
21163
|
const { columns, transactionDateType } = useContext(TransactionsListContext);
|
|
21152
21164
|
const { apiHost, darkMode } = useContext(BunnyContext);
|
|
@@ -21168,11 +21180,11 @@ const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
|
21168
21180
|
backgroundColor: index % 2 === 0
|
|
21169
21181
|
? `var(--row-background${darkMode ? '-dark' : ''})`
|
|
21170
21182
|
: `var(--row-background-alternate${darkMode ? '-dark' : ''})`,
|
|
21171
|
-
}, children: [jsx(TransactionGridCell, { children: jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [(showTitle || showState) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showTitle && (jsxs(Fragment, { children: [jsx(Text$
|
|
21183
|
+
}, children: [jsx(TransactionGridCell, { children: jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [(showTitle || showState) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showTitle && (jsxs(Fragment, { children: [jsx(Text$r, { children: lodashExports.capitalize(transaction.kind.toLowerCase()) }), jsx(TransactionRowTitle, { transaction: transaction })] })), showState && jsx(StateTag, { state: transaction.state })] })), jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showAccountName && jsx(Text$r, { children: (_a = transaction.account) === null || _a === void 0 ? void 0 : _a.name }), showAccountName && showDate && jsx(Text$r, { children: "\u00B7" }), showDate && (jsx(TransactionDate, { date: transactionDateToDisplay(transaction, transactionDateType) })), showDate && showAmount && jsx(Text$r, { children: "\u00B7" }), showAmount && (jsx(Text$r, { children: formatCurrency$1(transaction.transactionable.amount || transaction.amount, transaction.currencyId) }))] })] }) }), showDownload && (jsx(TransactionGridCell, { right: true, children: jsx(TransactionDownload, { transaction: transaction, token: token, apiHost: apiHost }) }))] }, index));
|
|
21172
21184
|
}) }));
|
|
21173
21185
|
};
|
|
21174
21186
|
|
|
21175
|
-
const { Text: Text$
|
|
21187
|
+
const { Text: Text$q } = Typography;
|
|
21176
21188
|
const DISPLAY_WIDTH = 1200;
|
|
21177
21189
|
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 = [
|
|
21178
21190
|
TransactionKind.INVOICE,
|
|
@@ -21276,7 +21288,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
|
|
|
21276
21288
|
onTransactionDisplayClose === null || onTransactionDisplayClose === void 0 ? void 0 : onTransactionDisplayClose(selectedTransaction);
|
|
21277
21289
|
setDrawerOpen(false);
|
|
21278
21290
|
}
|
|
21279
|
-
return (jsxs("div", { style: style, children: [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 ? (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsx(Text$
|
|
21291
|
+
return (jsxs("div", { style: style, children: [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 ? (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsx(Text$q, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsx("div", {}) // Empty div so justify-between works
|
|
21280
21292
|
), showSearchBar && (jsx("div", { className: `${isMobile ? 'bunny-w-full' : ''}`, children: jsx(Input, { className: searchBarClassName ? searchBarClassName : '', onChange: e => {
|
|
21281
21293
|
const value = e.target.value;
|
|
21282
21294
|
// Allow empty string, numbers, and decimal point
|
|
@@ -21399,7 +21411,7 @@ const useHasTaxPlugin = ({ apiHost, token, }) => {
|
|
|
21399
21411
|
return Boolean(plugins === null || plugins === void 0 ? void 0 : plugins.some((plugin) => plugin.type === "taxation"));
|
|
21400
21412
|
};
|
|
21401
21413
|
|
|
21402
|
-
const MUTATION$
|
|
21414
|
+
const MUTATION$6 = () => `
|
|
21403
21415
|
mutation AccountSignup (
|
|
21404
21416
|
$pluginId: String!,
|
|
21405
21417
|
$paymentMethodId: String,
|
|
@@ -21473,7 +21485,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21473
21485
|
priceListCode,
|
|
21474
21486
|
};
|
|
21475
21487
|
const response = await gqlRequest({
|
|
21476
|
-
query: MUTATION$
|
|
21488
|
+
query: MUTATION$6(),
|
|
21477
21489
|
token,
|
|
21478
21490
|
vars,
|
|
21479
21491
|
apiHost,
|
|
@@ -21484,7 +21496,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21484
21496
|
return response === null || response === void 0 ? void 0 : response.accountSignup;
|
|
21485
21497
|
};
|
|
21486
21498
|
|
|
21487
|
-
const MUTATION$
|
|
21499
|
+
const MUTATION$5 = () => `
|
|
21488
21500
|
mutation QuoteAccountSignup (
|
|
21489
21501
|
$accountName: String!,
|
|
21490
21502
|
$billingContact: ContactAttributes!,
|
|
@@ -21561,7 +21573,7 @@ const quoteAccountSignup = async ({ token, apiHost, priceListCode, accountName,
|
|
|
21561
21573
|
billingDetails,
|
|
21562
21574
|
};
|
|
21563
21575
|
const response = await gqlRequest({
|
|
21564
|
-
query: MUTATION$
|
|
21576
|
+
query: MUTATION$5(),
|
|
21565
21577
|
token,
|
|
21566
21578
|
vars,
|
|
21567
21579
|
apiHost,
|
|
@@ -21639,7 +21651,7 @@ const QUOTE_RECALCULATE_TAXES = `
|
|
|
21639
21651
|
}
|
|
21640
21652
|
}
|
|
21641
21653
|
`;
|
|
21642
|
-
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
21654
|
+
const quoteRecalculateTaxes$2 = async ({ quoteId, apiHost, token, }) => {
|
|
21643
21655
|
var _a, _b;
|
|
21644
21656
|
const vars = { id: quoteId };
|
|
21645
21657
|
const response = await gqlRequest({
|
|
@@ -21654,7 +21666,7 @@ const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
|
21654
21666
|
return (_b = response.quoteRecalculateTaxes) === null || _b === void 0 ? void 0 : _b.quote;
|
|
21655
21667
|
};
|
|
21656
21668
|
|
|
21657
|
-
const MUTATION$
|
|
21669
|
+
const MUTATION$4 = () => `
|
|
21658
21670
|
query PriceList($code: String!) {
|
|
21659
21671
|
priceList (code: $code) {
|
|
21660
21672
|
basePrice
|
|
@@ -21679,7 +21691,7 @@ query PriceList($code: String!) {
|
|
|
21679
21691
|
}`;
|
|
21680
21692
|
const getPriceList = async ({ token, code, apiHost, }) => {
|
|
21681
21693
|
const response = await gqlRequest({
|
|
21682
|
-
query: MUTATION$
|
|
21694
|
+
query: MUTATION$4(),
|
|
21683
21695
|
token,
|
|
21684
21696
|
vars: { code },
|
|
21685
21697
|
apiHost,
|
|
@@ -21689,16 +21701,60 @@ const getPriceList = async ({ token, code, apiHost, }) => {
|
|
|
21689
21701
|
|
|
21690
21702
|
const SubscriptionsContext = createContext({});
|
|
21691
21703
|
|
|
21704
|
+
const QuoteContext = createContext({});
|
|
21705
|
+
|
|
21692
21706
|
const graphql = initGraphQLTada();
|
|
21693
21707
|
|
|
21694
|
-
|
|
21695
|
-
if (
|
|
21696
|
-
return
|
|
21697
|
-
if (
|
|
21698
|
-
return
|
|
21699
|
-
if (
|
|
21700
|
-
return
|
|
21701
|
-
|
|
21708
|
+
const periodMonthsConverter = (period) => {
|
|
21709
|
+
if (period === 0)
|
|
21710
|
+
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
21711
|
+
else if (period === 1)
|
|
21712
|
+
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
21713
|
+
else if (period === 3)
|
|
21714
|
+
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
21715
|
+
else if (period === 6)
|
|
21716
|
+
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
21717
|
+
else if (period === 12)
|
|
21718
|
+
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
21719
|
+
else
|
|
21720
|
+
return null;
|
|
21721
|
+
};
|
|
21722
|
+
const billingPeriodConverter = (period) => {
|
|
21723
|
+
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
21724
|
+
return 0;
|
|
21725
|
+
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
21726
|
+
return 1;
|
|
21727
|
+
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
21728
|
+
return 3;
|
|
21729
|
+
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
21730
|
+
return 6;
|
|
21731
|
+
else
|
|
21732
|
+
return 12;
|
|
21733
|
+
};
|
|
21734
|
+
|
|
21735
|
+
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
21736
|
+
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
21737
|
+
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
21738
|
+
}
|
|
21739
|
+
|
|
21740
|
+
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
21741
|
+
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
21742
|
+
priceLists {
|
|
21743
|
+
id
|
|
21744
|
+
isVisible
|
|
21745
|
+
periodMonths
|
|
21746
|
+
}
|
|
21747
|
+
}
|
|
21748
|
+
`);
|
|
21749
|
+
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
21750
|
+
// Read fragments
|
|
21751
|
+
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
21752
|
+
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
21753
|
+
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
21754
|
+
var _a;
|
|
21755
|
+
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));
|
|
21756
|
+
});
|
|
21757
|
+
return unpurchasedAddonPriceLists.length > 0;
|
|
21702
21758
|
}
|
|
21703
21759
|
|
|
21704
21760
|
function hasUnpurchasedFeatureAddons(priceList, currentSubscription) {
|
|
@@ -21725,110 +21781,317 @@ function featureAddonSwitchTestId(addonName) {
|
|
|
21725
21781
|
return `feature-addon-switch-${name}`;
|
|
21726
21782
|
}
|
|
21727
21783
|
|
|
21728
|
-
const
|
|
21729
|
-
|
|
21730
|
-
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
21734
|
-
var _a, _b;
|
|
21735
|
-
const response = await gqlRequest({
|
|
21736
|
-
query: MUTATION$4,
|
|
21737
|
-
token,
|
|
21738
|
-
apiHost: apiHost,
|
|
21739
|
-
});
|
|
21740
|
-
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
|
|
21741
|
-
? response.currentUser.taxationRequiredAccountFields
|
|
21742
|
-
: null;
|
|
21784
|
+
const canSubscriptionUpgradeFromTrial = (subscription) => {
|
|
21785
|
+
var _a;
|
|
21786
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
21787
|
+
subscription.plan.selfServiceBuy) ||
|
|
21788
|
+
false;
|
|
21743
21789
|
};
|
|
21744
|
-
|
|
21745
|
-
|
|
21746
|
-
return (
|
|
21790
|
+
const canSubscriptionUpgradeFromTrialExpired = (subscription) => {
|
|
21791
|
+
var _a;
|
|
21792
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
21793
|
+
subscription.plan.selfServiceBuy) ||
|
|
21794
|
+
false;
|
|
21747
21795
|
};
|
|
21748
|
-
|
|
21749
|
-
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
const { privacyUrl, termsUrl } = currentUser;
|
|
21754
|
-
const isMobile = useIsMobile$1();
|
|
21755
|
-
return (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) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsx(BunnyMarketingLink, {})] }));
|
|
21796
|
+
const isSubscriptionNotActive = (subscription) => {
|
|
21797
|
+
var _a, _b, _c;
|
|
21798
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
21799
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
21800
|
+
((_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
21756
21801
|
};
|
|
21757
|
-
const
|
|
21758
|
-
|
|
21759
|
-
|
|
21760
|
-
|
|
21802
|
+
const isSubscriptionActiveOrPending = (subscription) => {
|
|
21803
|
+
var _a, _b;
|
|
21804
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'ACTIVE') ||
|
|
21805
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'PENDING');
|
|
21761
21806
|
};
|
|
21762
|
-
const
|
|
21763
|
-
|
|
21764
|
-
|
|
21765
|
-
|
|
21766
|
-
|
|
21767
|
-
}
|
|
21768
|
-
text-decoration: none;
|
|
21769
|
-
`;
|
|
21770
|
-
const StyledBunnyLink = styled(StyedLink) `
|
|
21771
|
-
&:hover {
|
|
21772
|
-
color: ${PRIMARY_COLOR} !important;
|
|
21773
|
-
}
|
|
21774
|
-
`;
|
|
21775
|
-
|
|
21776
|
-
const MUTATION$3 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
21777
|
-
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
21778
|
-
quoteChange {
|
|
21779
|
-
id
|
|
21780
|
-
charges {
|
|
21781
|
-
id
|
|
21782
|
-
amount
|
|
21783
|
-
couponId
|
|
21784
|
-
}
|
|
21785
|
-
}
|
|
21786
|
-
}
|
|
21787
|
-
}`;
|
|
21788
|
-
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
21807
|
+
const isSubscriptionTrial = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL'); };
|
|
21808
|
+
const isSubscriptionTrialExpired = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED'); };
|
|
21809
|
+
// Helper function to check if charge is a discount
|
|
21810
|
+
const isDiscount$1 = (kind) => kind === QuoteChangeKind.DISCOUNT || kind === QuoteChangeKind.FREE_PERIOD_DISCOUNT;
|
|
21811
|
+
const hasPriceTiers = (charge) => {
|
|
21789
21812
|
var _a;
|
|
21790
|
-
|
|
21791
|
-
const response = await gqlRequest({
|
|
21792
|
-
query: MUTATION$3,
|
|
21793
|
-
token,
|
|
21794
|
-
vars,
|
|
21795
|
-
apiHost,
|
|
21796
|
-
});
|
|
21797
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
21798
|
-
if (errors)
|
|
21799
|
-
throw errors;
|
|
21800
|
-
return response.quote;
|
|
21813
|
+
return Boolean((_a = charge === null || charge === void 0 ? void 0 : charge.priceTiers) === null || _a === void 0 ? void 0 : _a.length);
|
|
21801
21814
|
};
|
|
21802
21815
|
|
|
21803
|
-
const
|
|
21804
|
-
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
}
|
|
21808
|
-
`;
|
|
21809
|
-
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
21810
|
-
var _a;
|
|
21811
|
-
const vars = { couponCode, quoteChangeId };
|
|
21812
|
-
const response = await gqlRequest({
|
|
21813
|
-
query: MUTATION$2,
|
|
21814
|
-
token,
|
|
21815
|
-
vars,
|
|
21816
|
-
apiHost,
|
|
21817
|
-
});
|
|
21818
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeRemoveCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
21819
|
-
if (errors)
|
|
21820
|
-
throw errors;
|
|
21821
|
-
return response.quote;
|
|
21816
|
+
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
21817
|
+
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
21818
|
+
const createPlanDescription = (planDescription) => {
|
|
21819
|
+
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
21822
21820
|
};
|
|
21823
|
-
|
|
21824
|
-
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21821
|
+
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
21822
|
+
if (!priceList) {
|
|
21823
|
+
return;
|
|
21824
|
+
}
|
|
21825
|
+
// If a period option is selected, return the charge that matches the selected period option
|
|
21826
|
+
let activeBillingPLCharge;
|
|
21827
|
+
// Default to first price list charge
|
|
21828
|
+
let lowestPLCharge;
|
|
21829
|
+
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
21830
|
+
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
21831
|
+
activeBillingPLCharge = priceList.charges[0];
|
|
21832
|
+
}
|
|
21833
|
+
for (let j = 0; j < priceList.charges.length; j++) {
|
|
21834
|
+
const charge = priceList.charges[j];
|
|
21835
|
+
if (charge.chargeType === ChargeType.USAGE || charge.featureAddon === true)
|
|
21836
|
+
continue;
|
|
21837
|
+
if (activeBillingPLCharge) {
|
|
21838
|
+
// If we already found a charge with the same billing period check if this charge is lower
|
|
21839
|
+
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
21840
|
+
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
21841
|
+
activeBillingPLCharge = charge;
|
|
21842
|
+
}
|
|
21843
|
+
}
|
|
21844
|
+
// If a period option is selected, only return the charge if it matches the selected period option
|
|
21845
|
+
else if (selectedPriceList &&
|
|
21846
|
+
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
21847
|
+
activeBillingPLCharge = charge;
|
|
21848
|
+
}
|
|
21849
|
+
// Otherwise, return the lowest price list charge
|
|
21850
|
+
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
21851
|
+
lowestPLCharge = charge;
|
|
21828
21852
|
}
|
|
21829
21853
|
}
|
|
21830
|
-
|
|
21831
|
-
|
|
21854
|
+
return {
|
|
21855
|
+
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
21856
|
+
};
|
|
21857
|
+
};
|
|
21858
|
+
const showErrorNotification$3 = useErrorNotification();
|
|
21859
|
+
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
21860
|
+
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
21861
|
+
if (!priceListAddonPlans) {
|
|
21862
|
+
showErrorNotification$3('Price list addon plans are undefined');
|
|
21863
|
+
return false;
|
|
21864
|
+
}
|
|
21865
|
+
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
21866
|
+
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
21867
|
+
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription);
|
|
21868
|
+
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription);
|
|
21869
|
+
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
21870
|
+
// When should priceList be disabled?
|
|
21871
|
+
// if upgradingSubscription?.priceList.id === priceList.id
|
|
21872
|
+
// AND the upgradingSubscription is not in trial
|
|
21873
|
+
// AND cannot purchase feature addons
|
|
21874
|
+
// AND cannot purchase add-on plans
|
|
21875
|
+
// AND selfServiceBuy is false
|
|
21876
|
+
// if upgradingSubscription?.priceList.id != priceList.id
|
|
21877
|
+
// AND upgradingSubscription is expired trial
|
|
21878
|
+
if (isUpgradingSubscriptionPriceList) {
|
|
21879
|
+
return (!existingSubscriptionInTrial &&
|
|
21880
|
+
!existingSubscriptionInTrialExpired &&
|
|
21881
|
+
!canPurchaseFeatureAddons &&
|
|
21882
|
+
!canPurchasePlanAddons);
|
|
21883
|
+
}
|
|
21884
|
+
else {
|
|
21885
|
+
return false;
|
|
21886
|
+
}
|
|
21887
|
+
};
|
|
21888
|
+
|
|
21889
|
+
const CheckoutButton = ({ disabled, onClickCheckout, loading, tooltipText, }) => {
|
|
21890
|
+
const isMobile = useIsMobile$1();
|
|
21891
|
+
const TooltipWrapper = ({ children }) => {
|
|
21892
|
+
if (tooltipText) {
|
|
21893
|
+
return jsx(Tooltip, { title: tooltipText, children: children });
|
|
21894
|
+
}
|
|
21895
|
+
return jsx("div", { children: children });
|
|
21896
|
+
};
|
|
21897
|
+
return (jsx(TooltipWrapper, { children: jsx(Button, { className: isMobile ? 'w-full' : '', disabled: disabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
21898
|
+
};
|
|
21899
|
+
|
|
21900
|
+
var localizedFormat$2 = {exports: {}};
|
|
21901
|
+
|
|
21902
|
+
var localizedFormat$1 = localizedFormat$2.exports;
|
|
21903
|
+
|
|
21904
|
+
var hasRequiredLocalizedFormat;
|
|
21905
|
+
|
|
21906
|
+
function requireLocalizedFormat () {
|
|
21907
|
+
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
21908
|
+
hasRequiredLocalizedFormat = 1;
|
|
21909
|
+
(function (module, exports) {
|
|
21910
|
+
!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)};}}));
|
|
21911
|
+
} (localizedFormat$2));
|
|
21912
|
+
return localizedFormat$2.exports;
|
|
21913
|
+
}
|
|
21914
|
+
|
|
21915
|
+
var localizedFormatExports = requireLocalizedFormat();
|
|
21916
|
+
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
21917
|
+
|
|
21918
|
+
dayjs.extend(localizedFormat);
|
|
21919
|
+
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
21920
|
+
if (value !== 0 && !value)
|
|
21921
|
+
return '';
|
|
21922
|
+
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
21923
|
+
if (isNaN(currencyValue))
|
|
21924
|
+
return value;
|
|
21925
|
+
const localeOptions = {
|
|
21926
|
+
minimumFractionDigits: decimals,
|
|
21927
|
+
maximumFractionDigits: decimals,
|
|
21928
|
+
};
|
|
21929
|
+
localeOptions.style = 'currency';
|
|
21930
|
+
localeOptions.currency = currencyIsoCode;
|
|
21931
|
+
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
21932
|
+
};
|
|
21933
|
+
|
|
21934
|
+
const CheckoutPrice_QuoteFragment = t(`
|
|
21935
|
+
fragment CheckoutPrice_QuoteFragment on Quote {
|
|
21936
|
+
periodAmount
|
|
21937
|
+
amountDue
|
|
21938
|
+
}
|
|
21939
|
+
`);
|
|
21940
|
+
const CheckoutPrice = ({ isUsage, quote: maskedQuote, selectedPriceList, }) => {
|
|
21941
|
+
var _a;
|
|
21942
|
+
// Read fragments
|
|
21943
|
+
const quote = readFragment(CheckoutPrice_QuoteFragment, maskedQuote);
|
|
21944
|
+
// Hooks
|
|
21945
|
+
const isMobile = useIsMobile$1();
|
|
21946
|
+
// amountDue might not be available, so we use periodAmount as a fallback
|
|
21947
|
+
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;
|
|
21948
|
+
if (!isUsage && (!selectedPriceList || displayAmount === undefined))
|
|
21949
|
+
return null;
|
|
21950
|
+
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
21951
|
+
const periodLabel = convertedPeriodMonths ? PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
21952
|
+
return (jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
21953
|
+
? 'Usage based pricing'
|
|
21954
|
+
: selectedPriceList && displayAmount !== undefined
|
|
21955
|
+
? `${formatCurrency(displayAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, undefined)} / ${periodLabel}`
|
|
21956
|
+
: '' }));
|
|
21957
|
+
};
|
|
21958
|
+
|
|
21959
|
+
const { Text: Text$p } = Typography;
|
|
21960
|
+
const CheckoutBarSummarySection_QuoteFragment = t(`
|
|
21961
|
+
fragment CheckoutBarSummarySection_QuoteFragment on Quote {
|
|
21962
|
+
quoteChanges {
|
|
21963
|
+
charges {
|
|
21964
|
+
id
|
|
21965
|
+
}
|
|
21966
|
+
}
|
|
21967
|
+
...CheckoutPrice_QuoteFragment
|
|
21968
|
+
}
|
|
21969
|
+
`, [CheckoutPrice_QuoteFragment]);
|
|
21970
|
+
const CheckoutBarSummarySection = ({ selectedPriceList, onClickCheckout, }) => {
|
|
21971
|
+
var _a, _b;
|
|
21972
|
+
// Context
|
|
21973
|
+
const { quote: maskedQuote, isQuotePending, isUpdatingQuote } = useContext(QuoteContext);
|
|
21974
|
+
const quote = readFragment(CheckoutBarSummarySection_QuoteFragment, maskedQuote);
|
|
21975
|
+
const { isInPreviewMode } = useContext(SubscriptionsContext);
|
|
21976
|
+
// Hooks
|
|
21977
|
+
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
21978
|
+
const isMobile = useIsMobile$1();
|
|
21979
|
+
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
21980
|
+
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));
|
|
21981
|
+
const checkoutButtonDisabled = Boolean(!selectedPriceList || !quoteHasCharges || !hasPaymentPlugins || isInPreviewMode);
|
|
21982
|
+
const activeCharge = (_b = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _b === void 0 ? void 0 : _b.activeCharge;
|
|
21983
|
+
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === ChargeType.USAGE;
|
|
21984
|
+
return (jsxs(Text$p, { className: `bunny-flex bunny-items-center bunny-gap-4 ${isMobile ? 'bunny-flex-col' : ''}`, children: [quote && (jsxs("div", { className: `bunny-flex ${isMobile ? 'items-center justify-between w-full' : 'flex-col'}`, children: [jsx("div", { className: "bunny-text-slate-500 bunny-font-medium bunny-text-right", style: { fontSize: '11px' }, children: "TOTAL" }), jsx(CheckoutPrice, { isUsage: isUsage, quote: quote, selectedPriceList: selectedPriceList })] })), jsx(CheckoutButton, { disabled: checkoutButtonDisabled, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
21985
|
+
? 'Checkout is disabled in preview mode'
|
|
21986
|
+
: !hasPaymentPlugins
|
|
21987
|
+
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
21988
|
+
: undefined })] }));
|
|
21989
|
+
};
|
|
21990
|
+
|
|
21991
|
+
const MUTATION$3 = `{
|
|
21992
|
+
currentUser {
|
|
21993
|
+
taxationRequiredAccountFields
|
|
21994
|
+
}
|
|
21995
|
+
}`;
|
|
21996
|
+
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
21997
|
+
var _a, _b;
|
|
21998
|
+
const response = await gqlRequest({
|
|
21999
|
+
query: MUTATION$3,
|
|
22000
|
+
token,
|
|
22001
|
+
apiHost: apiHost,
|
|
22002
|
+
});
|
|
22003
|
+
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
|
|
22004
|
+
? response.currentUser.taxationRequiredAccountFields
|
|
22005
|
+
: null;
|
|
22006
|
+
};
|
|
22007
|
+
|
|
22008
|
+
const BunnyFooterIcon = ({ color }) => {
|
|
22009
|
+
return (jsxs("svg", { width: "45", height: "15", viewBox: "0 0 39 13", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxs("g", { clipPath: "url(#clip0_6_851)", children: [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 }), 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 }), 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 }), 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 }), 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 }), 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 })] }), jsx("defs", { children: jsx("clipPath", { id: "clip0_6_851", children: jsx("rect", { width: "39", height: "13", fill: "white" }) }) })] }));
|
|
22010
|
+
};
|
|
22011
|
+
|
|
22012
|
+
const { Text: Text$o } = Typography;
|
|
22013
|
+
const Footer = ({ className }) => {
|
|
22014
|
+
const token = useToken();
|
|
22015
|
+
const { currentUser } = useCurrentUserData(token);
|
|
22016
|
+
const { privacyUrl, termsUrl } = currentUser;
|
|
22017
|
+
const isMobile = useIsMobile$1();
|
|
22018
|
+
return (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) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsx(BunnyMarketingLink, {})] }));
|
|
22019
|
+
};
|
|
22020
|
+
const BunnyMarketingLink = () => {
|
|
22021
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
22022
|
+
const isMobile = useIsMobile$1();
|
|
22023
|
+
return (jsx("div", { className: `bunny-flex bunny-items-end bunny-justify-end ${isMobile ? '' : 'grow'}`, children: 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: jsxs("div", { className: "bunny-flex bunny-items-center", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsx(Text$o, { className: "bunny-text-slate-400", children: "Powered by\u00A0" }), jsx("div", { style: { paddingTop: '5px' }, children: jsx(BunnyFooterIcon, { color: isHovered ? PRIMARY_COLOR : SLATE_400 }) })] }) }) }));
|
|
22024
|
+
};
|
|
22025
|
+
const StyedLink = styled.a `
|
|
22026
|
+
color: ${SLATE_400};
|
|
22027
|
+
transition: color 0.3s;
|
|
22028
|
+
&:hover {
|
|
22029
|
+
color: ${SLATE_500};
|
|
22030
|
+
}
|
|
22031
|
+
text-decoration: none;
|
|
22032
|
+
`;
|
|
22033
|
+
const StyledBunnyLink = styled(StyedLink) `
|
|
22034
|
+
&:hover {
|
|
22035
|
+
color: ${PRIMARY_COLOR} !important;
|
|
22036
|
+
}
|
|
22037
|
+
`;
|
|
22038
|
+
|
|
22039
|
+
const MUTATION$2 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
22040
|
+
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
22041
|
+
quoteChange {
|
|
22042
|
+
id
|
|
22043
|
+
charges {
|
|
22044
|
+
id
|
|
22045
|
+
amount
|
|
22046
|
+
couponId
|
|
22047
|
+
}
|
|
22048
|
+
}
|
|
22049
|
+
}
|
|
22050
|
+
}`;
|
|
22051
|
+
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22052
|
+
var _a;
|
|
22053
|
+
const vars = { couponCode, quoteChangeId };
|
|
22054
|
+
const response = await gqlRequest({
|
|
22055
|
+
query: MUTATION$2,
|
|
22056
|
+
token,
|
|
22057
|
+
vars,
|
|
22058
|
+
apiHost,
|
|
22059
|
+
});
|
|
22060
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22061
|
+
if (errors)
|
|
22062
|
+
throw errors;
|
|
22063
|
+
return response.quote;
|
|
22064
|
+
};
|
|
22065
|
+
|
|
22066
|
+
const MUTATION$1 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
|
|
22067
|
+
quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
|
|
22068
|
+
errors
|
|
22069
|
+
}
|
|
22070
|
+
}
|
|
22071
|
+
`;
|
|
22072
|
+
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22073
|
+
var _a;
|
|
22074
|
+
const vars = { couponCode, quoteChangeId };
|
|
22075
|
+
const response = await gqlRequest({
|
|
22076
|
+
query: MUTATION$1,
|
|
22077
|
+
token,
|
|
22078
|
+
vars,
|
|
22079
|
+
apiHost,
|
|
22080
|
+
});
|
|
22081
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeRemoveCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22082
|
+
if (errors)
|
|
22083
|
+
throw errors;
|
|
22084
|
+
return response.quote;
|
|
22085
|
+
};
|
|
22086
|
+
|
|
22087
|
+
const COUPONS_QUERY = (filter) => `
|
|
22088
|
+
query Coupons {
|
|
22089
|
+
coupons(filter: ${filter ? `"${filter}"` : 'null'}) {
|
|
22090
|
+
totalCount
|
|
22091
|
+
}
|
|
22092
|
+
}
|
|
22093
|
+
`;
|
|
22094
|
+
const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
21832
22095
|
const response = await gqlRequest({
|
|
21833
22096
|
query: COUPONS_QUERY(filter),
|
|
21834
22097
|
token,
|
|
@@ -21838,7 +22101,7 @@ const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
|
21838
22101
|
return response === null || response === void 0 ? void 0 : response.coupons;
|
|
21839
22102
|
};
|
|
21840
22103
|
|
|
21841
|
-
const showErrorNotification$
|
|
22104
|
+
const showErrorNotification$2 = useErrorNotification();
|
|
21842
22105
|
const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCouponRemoved, }) => {
|
|
21843
22106
|
const { data: coupons } = useQuery({
|
|
21844
22107
|
queryKey: ['coupons', token],
|
|
@@ -21864,7 +22127,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
21864
22127
|
},
|
|
21865
22128
|
onError: (error) => {
|
|
21866
22129
|
var _a, _b;
|
|
21867
|
-
showErrorNotification$
|
|
22130
|
+
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');
|
|
21868
22131
|
},
|
|
21869
22132
|
});
|
|
21870
22133
|
const { mutate: removeCoupon, isPending: isRemovingCoupon } = useMutation({
|
|
@@ -21884,7 +22147,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
21884
22147
|
},
|
|
21885
22148
|
onError: (error) => {
|
|
21886
22149
|
var _a, _b;
|
|
21887
|
-
showErrorNotification$
|
|
22150
|
+
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');
|
|
21888
22151
|
},
|
|
21889
22152
|
});
|
|
21890
22153
|
return {
|
|
@@ -21984,7 +22247,7 @@ const QuoteFields_QuoteFragment = t(`
|
|
|
21984
22247
|
}
|
|
21985
22248
|
`);
|
|
21986
22249
|
|
|
21987
|
-
const MUTATION
|
|
22250
|
+
const MUTATION = `
|
|
21988
22251
|
mutation accountUpdate(
|
|
21989
22252
|
$id: ID!,
|
|
21990
22253
|
$attributes: AccountAttributes!) {
|
|
@@ -22005,11 +22268,11 @@ mutation accountUpdate(
|
|
|
22005
22268
|
}
|
|
22006
22269
|
}
|
|
22007
22270
|
`;
|
|
22008
|
-
const accountUpdate = async ({ accountId, attributes, token, apiHost, }) => {
|
|
22271
|
+
const accountUpdate$1 = async ({ accountId, attributes, token, apiHost, }) => {
|
|
22009
22272
|
var _a;
|
|
22010
22273
|
const vars = { id: accountId, attributes };
|
|
22011
22274
|
const response = await gqlRequest({
|
|
22012
|
-
query: MUTATION
|
|
22275
|
+
query: MUTATION,
|
|
22013
22276
|
token,
|
|
22014
22277
|
vars,
|
|
22015
22278
|
apiHost,
|
|
@@ -22030,7 +22293,7 @@ const TaxationForm = ({ account, accountId }) => {
|
|
|
22030
22293
|
// Mutations
|
|
22031
22294
|
const { mutate: updateAccount, isPending: isUpdatingAccount } = useMutation({
|
|
22032
22295
|
mutationFn: async (changedFormData) => {
|
|
22033
|
-
const account = await accountUpdate({
|
|
22296
|
+
const account = await accountUpdate$1({
|
|
22034
22297
|
accountId,
|
|
22035
22298
|
attributes: changedFormData,
|
|
22036
22299
|
token,
|
|
@@ -22056,6 +22319,7 @@ const FormBillingState = () => {
|
|
|
22056
22319
|
return (jsx(Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsx(Input, { placeholder: "State" }) }));
|
|
22057
22320
|
};
|
|
22058
22321
|
|
|
22322
|
+
const { Text: Text$n } = Typography;
|
|
22059
22323
|
// HACK: I have imported QuoteFields_QuoteFragment here as a hack to ensure I have all of the quote data needed for
|
|
22060
22324
|
// the eventual children of this component.
|
|
22061
22325
|
// Solution: Eventually all children of this component should be using query fragments to avoid this
|
|
@@ -22141,7 +22405,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
22141
22405
|
}
|
|
22142
22406
|
if (taxationRequiredAccountFields)
|
|
22143
22407
|
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
22144
|
-
return (jsx(
|
|
22408
|
+
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: paymentRequired ? (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote }), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsx(Fragment, { children: upgradingSubscription &&
|
|
22145
22409
|
shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) && (jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", quote: quote, onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsx(Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
22146
22410
|
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
22147
22411
|
var _a;
|
|
@@ -22150,7 +22414,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
22150
22414
|
removeCoupon(couponCode);
|
|
22151
22415
|
}
|
|
22152
22416
|
});
|
|
22153
|
-
}, children: "Remove coupon(s)" }))] })) : (
|
|
22417
|
+
}, children: "Remove coupon(s)" }))] })) : (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsx(Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsx(Text$n, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
22154
22418
|
};
|
|
22155
22419
|
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
22156
22420
|
const isMobile = useIsMobile$1();
|
|
@@ -22161,7 +22425,7 @@ const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
|
22161
22425
|
: {}
|
|
22162
22426
|
: {
|
|
22163
22427
|
width: '100%',
|
|
22164
|
-
maxWidth: '
|
|
22428
|
+
maxWidth: '400px',
|
|
22165
22429
|
}),
|
|
22166
22430
|
}, children: children }));
|
|
22167
22431
|
};
|
|
@@ -22177,7 +22441,7 @@ const Checkout_QuoteFragment = t(`
|
|
|
22177
22441
|
...QuoteCheckout_QuoteFragment
|
|
22178
22442
|
}
|
|
22179
22443
|
`, [QuoteCheckout_QuoteFragment]);
|
|
22180
|
-
const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
22444
|
+
const Checkout = ({ onCancel, onSuccess, onFail, onRecalculateTaxes, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
22181
22445
|
var _a, _b, _c, _d, _e;
|
|
22182
22446
|
const { apiHost } = useContext(BunnyContext);
|
|
22183
22447
|
const isMobile = useIsMobile$1();
|
|
@@ -22188,7 +22452,6 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22188
22452
|
apiHost,
|
|
22189
22453
|
token,
|
|
22190
22454
|
});
|
|
22191
|
-
const queryClient = useQueryClient();
|
|
22192
22455
|
// Queries
|
|
22193
22456
|
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = useQuery({
|
|
22194
22457
|
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
@@ -22199,26 +22462,15 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22199
22462
|
const { data: account, isLoading: isLoadingAccount } = useQuery({
|
|
22200
22463
|
queryKey: ['account', quote === null || quote === void 0 ? void 0 : quote.accountId],
|
|
22201
22464
|
queryFn: () => (quote === null || quote === void 0 ? void 0 : quote.accountId) &&
|
|
22202
|
-
getAccount({ id: quote.accountId, apiHost, token, componentsVersion: PACKAGE_VERSION }),
|
|
22465
|
+
getAccount$1({ id: quote.accountId, apiHost, token, componentsVersion: PACKAGE_VERSION }),
|
|
22203
22466
|
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
22204
22467
|
});
|
|
22468
|
+
// Use onRecalculateTaxes callback because parents need to define recalculateTaxes to get and set the right quote data they need
|
|
22205
22469
|
async function recalculateTaxes() {
|
|
22206
22470
|
if (quote) {
|
|
22207
22471
|
if (!quote.id)
|
|
22208
22472
|
throw new Error('Quote ID is required');
|
|
22209
|
-
|
|
22210
|
-
quoteId: quote.id,
|
|
22211
|
-
apiHost,
|
|
22212
|
-
token,
|
|
22213
|
-
});
|
|
22214
|
-
if (updatedQuote) {
|
|
22215
|
-
const quoteKey = queryKeyFactory.createObjectKey({
|
|
22216
|
-
id: updatedQuote.id,
|
|
22217
|
-
objectName: 'editingQuote',
|
|
22218
|
-
token,
|
|
22219
|
-
});
|
|
22220
|
-
queryClient.setQueryData(quoteKey, updatedQuote);
|
|
22221
|
-
}
|
|
22473
|
+
onRecalculateTaxes(quote.id);
|
|
22222
22474
|
}
|
|
22223
22475
|
return {};
|
|
22224
22476
|
}
|
|
@@ -22252,9 +22504,17 @@ const Checkout = ({ onCancel, onSuccess, onFail, invoice, open, quote: maskedQuo
|
|
|
22252
22504
|
} })) : (jsx(PaymentForm, { onPaymentSuccess: onSuccess }))] }), jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
22253
22505
|
};
|
|
22254
22506
|
|
|
22255
|
-
|
|
22507
|
+
function canEditChargeQuantity(charge) {
|
|
22508
|
+
if (!charge)
|
|
22509
|
+
return false;
|
|
22510
|
+
if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
|
|
22511
|
+
return false;
|
|
22512
|
+
if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
|
|
22513
|
+
return false;
|
|
22514
|
+
return true;
|
|
22515
|
+
}
|
|
22256
22516
|
|
|
22257
|
-
const { Text: Text$
|
|
22517
|
+
const { Text: Text$m } = Typography;
|
|
22258
22518
|
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
22259
22519
|
var _a;
|
|
22260
22520
|
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
|
|
@@ -22267,7 +22527,7 @@ const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChang
|
|
|
22267
22527
|
setIsTooltipOpen(false);
|
|
22268
22528
|
}, 6000);
|
|
22269
22529
|
}, []);
|
|
22270
|
-
return (jsxs(Text$
|
|
22530
|
+
return (jsxs(Text$m, { className: `bunny-flex bunny-items-center bunny-gap-2 ${isMobile ? 'bunny-justify-between' : ''}`, children: [jsx(QuantityLabel, { activeCharge: priceListCharge }), jsx(Tooltip, { onOpenChange: setIsTooltipOpen, open: isTooltipOpen, title: "Change quantity here", styles: {
|
|
22271
22531
|
body: {
|
|
22272
22532
|
paddingTop: '0.75rem',
|
|
22273
22533
|
paddingBottom: '0.75rem',
|
|
@@ -22278,222 +22538,7 @@ const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChang
|
|
|
22278
22538
|
};
|
|
22279
22539
|
const QuantityLabel = ({ activeCharge }) => {
|
|
22280
22540
|
const chargeName = activeCharge.name;
|
|
22281
|
-
return (jsx(Text$
|
|
22282
|
-
};
|
|
22283
|
-
|
|
22284
|
-
const periodMonthsConverter = (period) => {
|
|
22285
|
-
if (period === 0)
|
|
22286
|
-
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
22287
|
-
else if (period === 1)
|
|
22288
|
-
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
22289
|
-
else if (period === 3)
|
|
22290
|
-
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
22291
|
-
else if (period === 6)
|
|
22292
|
-
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
22293
|
-
else if (period === 12)
|
|
22294
|
-
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
22295
|
-
else
|
|
22296
|
-
return null;
|
|
22297
|
-
};
|
|
22298
|
-
const billingPeriodConverter = (period) => {
|
|
22299
|
-
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
22300
|
-
return 0;
|
|
22301
|
-
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
22302
|
-
return 1;
|
|
22303
|
-
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
22304
|
-
return 3;
|
|
22305
|
-
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
22306
|
-
return 6;
|
|
22307
|
-
else
|
|
22308
|
-
return 12;
|
|
22309
|
-
};
|
|
22310
|
-
|
|
22311
|
-
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
22312
|
-
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
22313
|
-
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
22314
|
-
}
|
|
22315
|
-
|
|
22316
|
-
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
22317
|
-
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
22318
|
-
priceLists {
|
|
22319
|
-
id
|
|
22320
|
-
isVisible
|
|
22321
|
-
periodMonths
|
|
22322
|
-
}
|
|
22323
|
-
}
|
|
22324
|
-
`);
|
|
22325
|
-
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
22326
|
-
// Read fragments
|
|
22327
|
-
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
22328
|
-
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
22329
|
-
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
22330
|
-
var _a;
|
|
22331
|
-
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));
|
|
22332
|
-
});
|
|
22333
|
-
return unpurchasedAddonPriceLists.length > 0;
|
|
22334
|
-
}
|
|
22335
|
-
|
|
22336
|
-
const canSubscriptionUpgradeFromTrial = (subscription) => {
|
|
22337
|
-
var _a;
|
|
22338
|
-
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
22339
|
-
subscription.plan.selfServiceBuy) ||
|
|
22340
|
-
false;
|
|
22341
|
-
};
|
|
22342
|
-
const canSubscriptionUpgradeFromTrialExpired = (subscription) => {
|
|
22343
|
-
var _a;
|
|
22344
|
-
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
22345
|
-
subscription.plan.selfServiceBuy) ||
|
|
22346
|
-
false;
|
|
22347
|
-
};
|
|
22348
|
-
const isSubscriptionNotActive = (subscription) => {
|
|
22349
|
-
var _a, _b, _c;
|
|
22350
|
-
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
22351
|
-
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
22352
|
-
((_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
22353
|
-
};
|
|
22354
|
-
const isSubscriptionActiveOrPending = (subscription) => {
|
|
22355
|
-
var _a, _b;
|
|
22356
|
-
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'ACTIVE') ||
|
|
22357
|
-
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'PENDING');
|
|
22358
|
-
};
|
|
22359
|
-
const isSubscriptionTrial = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL'); };
|
|
22360
|
-
const isSubscriptionTrialExpired = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED'); };
|
|
22361
|
-
// Helper function to check if charge is a discount
|
|
22362
|
-
const isDiscount$1 = (kind) => kind === QuoteChangeKind.DISCOUNT || kind === QuoteChangeKind.FREE_PERIOD_DISCOUNT;
|
|
22363
|
-
const hasPriceTiers = (charge) => {
|
|
22364
|
-
var _a;
|
|
22365
|
-
return Boolean((_a = charge === null || charge === void 0 ? void 0 : charge.priceTiers) === null || _a === void 0 ? void 0 : _a.length);
|
|
22366
|
-
};
|
|
22367
|
-
|
|
22368
|
-
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
22369
|
-
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
22370
|
-
const createPlanDescription = (planDescription) => {
|
|
22371
|
-
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
22372
|
-
};
|
|
22373
|
-
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
22374
|
-
if (!priceList) {
|
|
22375
|
-
return;
|
|
22376
|
-
}
|
|
22377
|
-
// If a period option is selected, return the charge that matches the selected period option
|
|
22378
|
-
let activeBillingPLCharge;
|
|
22379
|
-
// Default to first price list charge
|
|
22380
|
-
let lowestPLCharge;
|
|
22381
|
-
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
22382
|
-
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
22383
|
-
activeBillingPLCharge = priceList.charges[0];
|
|
22384
|
-
}
|
|
22385
|
-
for (let j = 0; j < priceList.charges.length; j++) {
|
|
22386
|
-
const charge = priceList.charges[j];
|
|
22387
|
-
if (charge.chargeType === ChargeType.USAGE || charge.featureAddon === true)
|
|
22388
|
-
continue;
|
|
22389
|
-
if (activeBillingPLCharge) {
|
|
22390
|
-
// If we already found a charge with the same billing period check if this charge is lower
|
|
22391
|
-
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
22392
|
-
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
22393
|
-
activeBillingPLCharge = charge;
|
|
22394
|
-
}
|
|
22395
|
-
}
|
|
22396
|
-
// If a period option is selected, only return the charge if it matches the selected period option
|
|
22397
|
-
else if (selectedPriceList &&
|
|
22398
|
-
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
22399
|
-
activeBillingPLCharge = charge;
|
|
22400
|
-
}
|
|
22401
|
-
// Otherwise, return the lowest price list charge
|
|
22402
|
-
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
22403
|
-
lowestPLCharge = charge;
|
|
22404
|
-
}
|
|
22405
|
-
}
|
|
22406
|
-
return {
|
|
22407
|
-
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
22408
|
-
};
|
|
22409
|
-
};
|
|
22410
|
-
const showErrorNotification$2 = useErrorNotification();
|
|
22411
|
-
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
22412
|
-
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
22413
|
-
if (!priceListAddonPlans) {
|
|
22414
|
-
showErrorNotification$2('Price list addon plans are undefined');
|
|
22415
|
-
return false;
|
|
22416
|
-
}
|
|
22417
|
-
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
22418
|
-
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
22419
|
-
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription);
|
|
22420
|
-
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription);
|
|
22421
|
-
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
22422
|
-
// When should priceList be disabled?
|
|
22423
|
-
// if upgradingSubscription?.priceList.id === priceList.id
|
|
22424
|
-
// AND the upgradingSubscription is not in trial
|
|
22425
|
-
// AND cannot purchase feature addons
|
|
22426
|
-
// AND cannot purchase add-on plans
|
|
22427
|
-
// AND selfServiceBuy is false
|
|
22428
|
-
// if upgradingSubscription?.priceList.id != priceList.id
|
|
22429
|
-
// AND upgradingSubscription is expired trial
|
|
22430
|
-
if (isUpgradingSubscriptionPriceList) {
|
|
22431
|
-
return (!existingSubscriptionInTrial &&
|
|
22432
|
-
!existingSubscriptionInTrialExpired &&
|
|
22433
|
-
!canPurchaseFeatureAddons &&
|
|
22434
|
-
!canPurchasePlanAddons);
|
|
22435
|
-
}
|
|
22436
|
-
else {
|
|
22437
|
-
return false;
|
|
22438
|
-
}
|
|
22439
|
-
};
|
|
22440
|
-
|
|
22441
|
-
const CheckoutButton = ({ checkoutButtonDisabled, onClickCheckout, loading, tooltipText, }) => {
|
|
22442
|
-
const isMobile = useIsMobile$1();
|
|
22443
|
-
const TooltipWrapper = ({ children }) => {
|
|
22444
|
-
if (tooltipText) {
|
|
22445
|
-
return jsx(Tooltip, { title: tooltipText, children: children });
|
|
22446
|
-
}
|
|
22447
|
-
return jsx("div", { children: children });
|
|
22448
|
-
};
|
|
22449
|
-
return (jsx(TooltipWrapper, { children: jsx(Button, { className: isMobile ? 'w-full' : '', disabled: checkoutButtonDisabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
22450
|
-
};
|
|
22451
|
-
|
|
22452
|
-
const CheckoutPrice = ({ isUsage, quote, selectedPriceList, }) => {
|
|
22453
|
-
const isMobile = useIsMobile$1();
|
|
22454
|
-
if (!isUsage && (!selectedPriceList || (quote === null || quote === void 0 ? void 0 : quote.periodAmount) === undefined))
|
|
22455
|
-
return null;
|
|
22456
|
-
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
22457
|
-
const periodLabel = convertedPeriodMonths ? PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
22458
|
-
return (jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
22459
|
-
? 'Usage based pricing'
|
|
22460
|
-
: selectedPriceList && (quote === null || quote === void 0 ? void 0 : quote.periodAmount) !== undefined
|
|
22461
|
-
? `${formatCurrency$1(quote.periodAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, 0)} / ${periodLabel}`
|
|
22462
|
-
: '' }));
|
|
22463
|
-
};
|
|
22464
|
-
|
|
22465
|
-
const { Text: Text$m } = Typography;
|
|
22466
|
-
const CheckoutBarSummarySection = ({ open, selectedPriceList, onClickCheckout, }) => {
|
|
22467
|
-
var _a;
|
|
22468
|
-
// Context
|
|
22469
|
-
const { quote: quoteData, isQuotePending, isUpdatingQuote } = useContext(QuoteContext);
|
|
22470
|
-
const quote = quoteData;
|
|
22471
|
-
const { upgradingSubscription, isInPreviewMode } = useContext(SubscriptionsContext);
|
|
22472
|
-
// Hooks
|
|
22473
|
-
const token = useToken();
|
|
22474
|
-
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
22475
|
-
const queryClient = useQueryClient();
|
|
22476
|
-
const isMobile = useIsMobile$1();
|
|
22477
|
-
// Derived state
|
|
22478
|
-
const isFetching = queryClient.isFetching({
|
|
22479
|
-
queryKey: QueryKeyFactory$1.default.planChangeOptionsKey({
|
|
22480
|
-
subscriptionId: upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.id,
|
|
22481
|
-
token,
|
|
22482
|
-
}),
|
|
22483
|
-
});
|
|
22484
|
-
// When should checkout button be disabled?
|
|
22485
|
-
const isUpdatingCharges = (quote === null || quote === void 0 ? void 0 : quote.quoteChanges.some(qc => qc.kind === 'UPDATE' && qc.charges.length > 0)) || false;
|
|
22486
|
-
const isUpgradingSubscription = selectedPriceList.id !== (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id);
|
|
22487
|
-
const disableCheckoutButton = Boolean(!selectedPriceList || isFetching || !(isUpgradingSubscription || isUpdatingCharges) || open);
|
|
22488
|
-
const checkoutButtonDisabled = (quote === null || quote === void 0 ? void 0 : quote.amountDue) && (quote === null || quote === void 0 ? void 0 : quote.amountDue) > 0 ? false : disableCheckoutButton;
|
|
22489
|
-
const activeCharge = (_a = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _a === void 0 ? void 0 : _a.activeCharge;
|
|
22490
|
-
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === ChargeType.USAGE;
|
|
22491
|
-
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
22492
|
-
return (jsxs(Text$m, { className: `bunny-flex bunny-items-center bunny-gap-4 ${isMobile ? 'bunny-flex-col' : ''}`, children: [quote && (jsxs("div", { className: `bunny-flex ${isMobile ? 'items-center justify-between w-full' : 'flex-col'}`, children: [jsx("div", { className: "bunny-text-slate-500 bunny-font-medium bunny-text-right", style: { fontSize: '11px' }, children: "TOTAL" }), jsx(CheckoutPrice, { isUsage: isUsage, quote: quote, selectedPriceList: selectedPriceList })] })), jsx(CheckoutButton, { checkoutButtonDisabled: checkoutButtonDisabled || !hasPaymentPlugins || isInPreviewMode, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
22493
|
-
? 'Checkout is disabled in preview mode'
|
|
22494
|
-
: !hasPaymentPlugins
|
|
22495
|
-
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
22496
|
-
: undefined })] }));
|
|
22541
|
+
return (jsx(Text$m, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
22497
22542
|
};
|
|
22498
22543
|
|
|
22499
22544
|
const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
@@ -22513,8 +22558,8 @@ const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
|
22513
22558
|
`, [Checkout_QuoteFragment]);
|
|
22514
22559
|
const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onCheckoutSuccess, }) => {
|
|
22515
22560
|
// Context
|
|
22516
|
-
const { shadow
|
|
22517
|
-
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, isFeatureAddonsLoading, isUpdatingQuote, } = useContext(QuoteContext);
|
|
22561
|
+
const { shadow } = useContext(SubscriptionsContext);
|
|
22562
|
+
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, onRecalculateTaxes, isFeatureAddonsLoading, isUpdatingQuote, } = useContext(QuoteContext);
|
|
22518
22563
|
// Read fragments
|
|
22519
22564
|
const quote = readFragment(PlanPickerCheckoutBar_QuoteFragment, maskedQuote);
|
|
22520
22565
|
// Local state
|
|
@@ -22562,9 +22607,6 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22562
22607
|
const isFeatureAddon = charge.featureAddon;
|
|
22563
22608
|
const quantity = getFeatureQuantity((_d = charge.feature) === null || _d === void 0 ? void 0 : _d.id, charge.id);
|
|
22564
22609
|
const maybeIsChargeLoading = isFeatureAddon && isFeatureAddonsLoading;
|
|
22565
|
-
const showInput = selectedPriceList.id !== (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id);
|
|
22566
|
-
if (!isFeatureAddon && !showInput)
|
|
22567
|
-
return null;
|
|
22568
22610
|
if (!quantity)
|
|
22569
22611
|
return null;
|
|
22570
22612
|
// if charge is a feature addon, and a corresponding quote charge is not found in quote, return null
|
|
@@ -22575,9 +22617,40 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22575
22617
|
return (jsx(CheckoutBarInput, { disabled: isDisabled, priceListCharge: charge, quantity: quantity, onQuantityChanged: quantity => {
|
|
22576
22618
|
onChangeQuantity(charge.id, quantity);
|
|
22577
22619
|
} }, index));
|
|
22578
|
-
}) }), jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true),
|
|
22620
|
+
}) }), jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true), selectedPriceList: selectedPriceList }), 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 })] }));
|
|
22579
22621
|
};
|
|
22580
22622
|
|
|
22623
|
+
const useQuoteUpdateFeatureAddon_QuoteFragment = t(`
|
|
22624
|
+
fragment useQuoteUpdateFeatureAddon_QuoteFragment on Quote {
|
|
22625
|
+
id
|
|
22626
|
+
startDate
|
|
22627
|
+
}
|
|
22628
|
+
`);
|
|
22629
|
+
|
|
22630
|
+
const FeatureAddonRow_QuoteFragment = t(`
|
|
22631
|
+
fragment FeatureAddonRow_QuoteFragment on Quote {
|
|
22632
|
+
...useQuoteUpdateFeatureAddon_QuoteFragment
|
|
22633
|
+
}
|
|
22634
|
+
`, [useQuoteUpdateFeatureAddon_QuoteFragment]);
|
|
22635
|
+
|
|
22636
|
+
const useToggleAddonPlan_QuoteFragment = t(`
|
|
22637
|
+
fragment useToggleAddonPlan_QuoteFragment on Quote {
|
|
22638
|
+
quoteChanges {
|
|
22639
|
+
priceList {
|
|
22640
|
+
id
|
|
22641
|
+
}
|
|
22642
|
+
id
|
|
22643
|
+
}
|
|
22644
|
+
id
|
|
22645
|
+
}
|
|
22646
|
+
`);
|
|
22647
|
+
|
|
22648
|
+
const AddonPlanRow_QuoteFragment = t(`
|
|
22649
|
+
fragment AddonPlanRow_QuoteFragment on Quote {
|
|
22650
|
+
...useToggleAddonPlan_QuoteFragment
|
|
22651
|
+
}
|
|
22652
|
+
`, [useToggleAddonPlan_QuoteFragment]);
|
|
22653
|
+
|
|
22581
22654
|
/**
|
|
22582
22655
|
* Central quote fragment for QuoteProvider context.
|
|
22583
22656
|
*
|
|
@@ -22595,6 +22668,7 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22595
22668
|
id
|
|
22596
22669
|
currencyId
|
|
22597
22670
|
amountDue
|
|
22671
|
+
startDate
|
|
22598
22672
|
quoteChanges {
|
|
22599
22673
|
id
|
|
22600
22674
|
kind
|
|
@@ -22618,75 +22692,17 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22618
22692
|
}
|
|
22619
22693
|
}
|
|
22620
22694
|
...PlanPickerCheckoutBar_QuoteFragment
|
|
22621
|
-
|
|
22622
|
-
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
${removeFormattedQuoteField ? '' : `formattedQuote { html }`}
|
|
22633
|
-
id
|
|
22634
|
-
payableId
|
|
22635
|
-
periodAmount
|
|
22636
|
-
subtotal
|
|
22637
|
-
taxAmount
|
|
22638
|
-
startDate
|
|
22639
|
-
amountsByPeriod {
|
|
22640
|
-
amount
|
|
22641
|
-
startDate
|
|
22642
|
-
}
|
|
22643
|
-
kind
|
|
22644
|
-
quoteChanges {
|
|
22645
|
-
currencyId
|
|
22646
|
-
id
|
|
22647
|
-
kind
|
|
22648
|
-
charges {
|
|
22649
|
-
subtotal
|
|
22650
|
-
amountsByPeriod {
|
|
22651
|
-
amount
|
|
22652
|
-
startDate
|
|
22653
|
-
}
|
|
22654
|
-
amount
|
|
22655
|
-
billingPeriod
|
|
22656
|
-
currencyId
|
|
22657
|
-
feature {
|
|
22658
|
-
id
|
|
22659
|
-
unitName
|
|
22660
|
-
}
|
|
22661
|
-
id
|
|
22662
|
-
name
|
|
22663
|
-
priceListCharge {
|
|
22664
|
-
id
|
|
22665
|
-
quantityMax
|
|
22666
|
-
quantityMin
|
|
22667
|
-
selfServiceQuantity
|
|
22668
|
-
}
|
|
22669
|
-
priceList {
|
|
22670
|
-
id
|
|
22671
|
-
}
|
|
22672
|
-
coupon {
|
|
22673
|
-
couponCode
|
|
22674
|
-
}
|
|
22675
|
-
quantity
|
|
22676
|
-
kind
|
|
22677
|
-
}
|
|
22678
|
-
priceList {
|
|
22679
|
-
id
|
|
22680
|
-
plan {
|
|
22681
|
-
name
|
|
22682
|
-
}
|
|
22683
|
-
product {
|
|
22684
|
-
name
|
|
22685
|
-
}
|
|
22686
|
-
}
|
|
22687
|
-
}
|
|
22688
|
-
}
|
|
22689
|
-
`;
|
|
22695
|
+
...CheckoutBarSummarySection_QuoteFragment
|
|
22696
|
+
...AddonPlanRow_QuoteFragment
|
|
22697
|
+
...FeatureAddonRow_QuoteFragment
|
|
22698
|
+
}
|
|
22699
|
+
`, [
|
|
22700
|
+
PlanPickerCheckoutBar_QuoteFragment,
|
|
22701
|
+
CheckoutBarSummarySection_QuoteFragment,
|
|
22702
|
+
AddonPlanRow_QuoteFragment,
|
|
22703
|
+
FeatureAddonRow_QuoteFragment,
|
|
22704
|
+
]);
|
|
22705
|
+
|
|
22690
22706
|
const FormattedQuoteField_QuoteFragment = t(`
|
|
22691
22707
|
fragment FormattedQuoteField_QuoteFragment on Quote {
|
|
22692
22708
|
formattedQuote {
|
|
@@ -22694,7 +22710,7 @@ const FormattedQuoteField_QuoteFragment = t(`
|
|
|
22694
22710
|
}
|
|
22695
22711
|
}
|
|
22696
22712
|
`);
|
|
22697
|
-
const query$
|
|
22713
|
+
const query$5 = t(`
|
|
22698
22714
|
query quote($id: ID, $removeFormattedQuoteField: Boolean!) {
|
|
22699
22715
|
quote(id: $id) {
|
|
22700
22716
|
...QuoteContext_QuoteFragment
|
|
@@ -22703,7 +22719,7 @@ const query$3 = t(`
|
|
|
22703
22719
|
}
|
|
22704
22720
|
`, [QuoteContext_QuoteFragment, FormattedQuoteField_QuoteFragment]);
|
|
22705
22721
|
const getQuote$1 = async ({ id, token, apiHost, removeFormattedQuoteField = false, }) => {
|
|
22706
|
-
const response = await execute(query$
|
|
22722
|
+
const response = await execute(query$5, { apiHost, token }, { id, removeFormattedQuoteField });
|
|
22707
22723
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
22708
22724
|
};
|
|
22709
22725
|
|
|
@@ -22808,7 +22824,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
22808
22824
|
});
|
|
22809
22825
|
const { mutate: recalculateTaxesMutation } = useMutation({
|
|
22810
22826
|
mutationFn: (quoteId) => {
|
|
22811
|
-
return quoteRecalculateTaxes({ token, apiHost, quoteId });
|
|
22827
|
+
return quoteRecalculateTaxes$2({ token, apiHost, quoteId });
|
|
22812
22828
|
},
|
|
22813
22829
|
onError: (error) => {
|
|
22814
22830
|
if (!error[0].message.includes('Ensure that you have a taxation plugin')) {
|
|
@@ -22989,7 +23005,7 @@ const useQuoteQueryData = (quoteId) => {
|
|
|
22989
23005
|
return data;
|
|
22990
23006
|
};
|
|
22991
23007
|
|
|
22992
|
-
const useSetQuoteQueryData = () => {
|
|
23008
|
+
const useSetQuoteQueryData$1 = () => {
|
|
22993
23009
|
const token = useToken();
|
|
22994
23010
|
const queryClient = useQueryClient();
|
|
22995
23011
|
const setQuoteQueryData = (quoteId, quote) => {
|
|
@@ -23028,6 +23044,9 @@ const QuantityInput_QuoteFragment = t(`
|
|
|
23028
23044
|
}
|
|
23029
23045
|
`, []);
|
|
23030
23046
|
|
|
23047
|
+
const useQuoteIsLoadingState = (isLoading) => useState(isLoading !== null && isLoading !== void 0 ? isLoading : false);
|
|
23048
|
+
const [QuoteIsLoadingProvider, useQuoteIsLoading] = createStateContext(useQuoteIsLoadingState);
|
|
23049
|
+
|
|
23031
23050
|
const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
23032
23051
|
fragment QuoteChangeSummarySection_QuoteFragment on Quote {
|
|
23033
23052
|
id
|
|
@@ -23039,10 +23058,11 @@ const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
|
23039
23058
|
const QuoteChangeSummarySection = ({ openCheckout, errorUpdatingQuantity, }) => {
|
|
23040
23059
|
const isMobile = useIsMobile$1();
|
|
23041
23060
|
const [quoteId] = useQuoteId();
|
|
23061
|
+
const [isQuoteLoading] = useQuoteIsLoading();
|
|
23042
23062
|
const maskedQuote = useQuoteQueryData(quoteId);
|
|
23043
23063
|
const quote = readFragment(QuoteChangeSummarySection_QuoteFragment, maskedQuote);
|
|
23044
|
-
const disabled = !quoteId || !quote || errorUpdatingQuantity;
|
|
23045
|
-
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: [quote && !disabled && (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-mb-8", children: [jsx("div", { className: "bunny-text-slate-500 bunny-text-right bunny-text-xs bunny-mb-2", children: "TOTAL" }), jsx("div", { className: `bunny-text-right ${isMobile ? 'bunny-text-2xl' : 'bunny-text-xl'}`, children: formatCurrency$1(getQuoteAmountDue(quote), (quote === null || quote === void 0 ? void 0 : quote.currencyId) || '') })] })), jsx("div", { className: `bunny-flex bunny-items-center bunny-justify-end ${isMobile ? 'bunny-w-full' : ''}`, children: jsx(Button, { className: "bunny-w-full", onClick: openCheckout, disabled: disabled, size: isMobile ? 'large' : 'middle', type: "primary", children: "Proceed to checkout" }) })] }));
|
|
23064
|
+
const disabled = !quoteId || !quote || errorUpdatingQuantity || isQuoteLoading;
|
|
23065
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: [quote && !disabled && (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-mb-8", children: [jsx("div", { className: "bunny-text-slate-500 bunny-text-right bunny-text-xs bunny-mb-2", children: "TOTAL" }), jsx("div", { className: `bunny-text-right ${isMobile ? 'bunny-text-2xl' : 'bunny-text-xl'}`, children: formatCurrency$1(getQuoteAmountDue(quote), (quote === null || quote === void 0 ? void 0 : quote.currencyId) || '') })] })), jsx("div", { className: `bunny-flex bunny-items-center bunny-justify-end ${isMobile ? 'bunny-w-full' : ''}`, children: jsx(Button, { className: "bunny-w-full", onClick: openCheckout, disabled: disabled, size: isMobile ? 'large' : 'middle', type: "primary", loading: isQuoteLoading, children: "Proceed to checkout" }) })] }));
|
|
23046
23066
|
};
|
|
23047
23067
|
|
|
23048
23068
|
const QuantityDrawer_QuoteFragment = t(`
|
|
@@ -23054,7 +23074,7 @@ const QuantityDrawer_QuoteFragment = t(`
|
|
|
23054
23074
|
}
|
|
23055
23075
|
`, [Checkout_QuoteFragment, QuantityInput_QuoteFragment, QuoteChangeSummarySection_QuoteFragment]);
|
|
23056
23076
|
|
|
23057
|
-
const mutation$
|
|
23077
|
+
const mutation$c = t(`
|
|
23058
23078
|
mutation QuoteChargeCreate(
|
|
23059
23079
|
$quoteChangeId: ID!
|
|
23060
23080
|
$startDate: ISO8601Date!
|
|
@@ -23089,11 +23109,11 @@ const mutation$4 = t(`
|
|
|
23089
23109
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23090
23110
|
const quoteChargeCreate$1 = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
23091
23111
|
var _a;
|
|
23092
|
-
const response = await execute(mutation$
|
|
23112
|
+
const response = await execute(mutation$c, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
23093
23113
|
return (_a = response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
23094
23114
|
};
|
|
23095
23115
|
|
|
23096
|
-
const mutation$
|
|
23116
|
+
const mutation$b = t(`
|
|
23097
23117
|
mutation QuoteChargeUpdate($quoteChargeId: ID!, $quantity: Int) {
|
|
23098
23118
|
quoteChargeUpdate(quoteChargeId: $quoteChargeId, quantity: $quantity) {
|
|
23099
23119
|
quoteCharge {
|
|
@@ -23112,14 +23132,29 @@ const mutation$3 = t(`
|
|
|
23112
23132
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23113
23133
|
const quoteChargeUpdate = async (quoteChargeId, quantity, apiHost, token) => {
|
|
23114
23134
|
var _a, _b;
|
|
23115
|
-
const response = await execute(mutation$
|
|
23135
|
+
const response = await execute(mutation$b, { apiHost, token }, { quoteChargeId, quantity });
|
|
23116
23136
|
if ((_a = response.quoteChargeUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23117
23137
|
throw new Error(response.quoteChargeUpdate.errors[0]);
|
|
23118
23138
|
}
|
|
23119
23139
|
return (_b = response.quoteChargeUpdate) === null || _b === void 0 ? void 0 : _b.quoteCharge;
|
|
23120
23140
|
};
|
|
23121
23141
|
|
|
23122
|
-
const mutation$
|
|
23142
|
+
const mutation$a = t(`
|
|
23143
|
+
mutation QuoteDelete($id: ID!) {
|
|
23144
|
+
quoteDelete(id: $id) {
|
|
23145
|
+
errors
|
|
23146
|
+
quote {
|
|
23147
|
+
id
|
|
23148
|
+
}
|
|
23149
|
+
}
|
|
23150
|
+
}
|
|
23151
|
+
`, []);
|
|
23152
|
+
const quoteDelete = async ({ id, token, apiHost }) => {
|
|
23153
|
+
const response = await execute(mutation$a, { apiHost, token }, { id });
|
|
23154
|
+
return response.quoteDelete;
|
|
23155
|
+
};
|
|
23156
|
+
|
|
23157
|
+
const mutation$9 = t(`
|
|
23123
23158
|
mutation quoteSubscriptionUpdate($subscriptionIds: [ID!]!) {
|
|
23124
23159
|
quoteSubscriptionUpdate(subscriptionIds: $subscriptionIds) {
|
|
23125
23160
|
quote {
|
|
@@ -23148,7 +23183,7 @@ const mutation$2 = t(`
|
|
|
23148
23183
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23149
23184
|
const quoteSubscriptionUpdate = async (subscriptionIds, apiHost, token) => {
|
|
23150
23185
|
var _a, _b;
|
|
23151
|
-
const response = await execute(mutation$
|
|
23186
|
+
const response = await execute(mutation$9, { apiHost, token }, { subscriptionIds });
|
|
23152
23187
|
if ((_a = response.quoteSubscriptionUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23153
23188
|
throw new Error(response.quoteSubscriptionUpdate.errors[0]);
|
|
23154
23189
|
}
|
|
@@ -23217,6 +23252,23 @@ const canShowChangeQuantities = ({ subscriptions, }) => {
|
|
|
23217
23252
|
});
|
|
23218
23253
|
};
|
|
23219
23254
|
|
|
23255
|
+
/**
|
|
23256
|
+
* Note: It is good practice to isolate useEffects into their own components.
|
|
23257
|
+
* This approach helps prevent unnecessary re-renders when data is unchanged,
|
|
23258
|
+
* since useEffect will only be triggered in this dedicated sibling component.
|
|
23259
|
+
*/
|
|
23260
|
+
const QuoteIsLoadingUpdater = ({ quoteIsPending }) => {
|
|
23261
|
+
const [, setQuoteIsLoading] = useQuoteIsLoading();
|
|
23262
|
+
const prevValue = useRef(quoteIsPending);
|
|
23263
|
+
useEffect(() => {
|
|
23264
|
+
if (prevValue.current !== quoteIsPending) {
|
|
23265
|
+
setQuoteIsLoading(quoteIsPending);
|
|
23266
|
+
prevValue.current = quoteIsPending;
|
|
23267
|
+
}
|
|
23268
|
+
}, [quoteIsPending, setQuoteIsLoading]);
|
|
23269
|
+
return null;
|
|
23270
|
+
};
|
|
23271
|
+
|
|
23220
23272
|
const QuantityInput_SubscriptionChargeFragment = t(`
|
|
23221
23273
|
fragment QuantityInput_SubscriptionChargeFragment on SubscriptionCharge {
|
|
23222
23274
|
id
|
|
@@ -23228,7 +23280,6 @@ const QuantityInput_SubscriptionChargeFragment = t(`
|
|
|
23228
23280
|
const QuantityInput_SubscriptionFragment = t(`
|
|
23229
23281
|
fragment QuantityInput_SubscriptionFragment on Subscription {
|
|
23230
23282
|
id
|
|
23231
|
-
state
|
|
23232
23283
|
priceList {
|
|
23233
23284
|
id
|
|
23234
23285
|
}
|
|
@@ -23244,6 +23295,16 @@ const QuantityInput_SubscriptionFragment = t(`
|
|
|
23244
23295
|
CanShowQuantitiesInput_SubscriptionFragment,
|
|
23245
23296
|
]);
|
|
23246
23297
|
const DEBOUNCE_TIME$1 = 1000;
|
|
23298
|
+
/**
|
|
23299
|
+
* Design note:
|
|
23300
|
+
* If the quantity is cleared by the user (quantity becomes undefined), we delete the quote.
|
|
23301
|
+
*
|
|
23302
|
+
* Rationale:
|
|
23303
|
+
* The user may next change the quantity for a charge on a different subscription, and we need to
|
|
23304
|
+
* allow creating a new quote/quoteChange in that context. Currently there is no way to create a
|
|
23305
|
+
* quoteChange of kind "update" without first calling `quoteSubscriptionUpdate`, so we delete the
|
|
23306
|
+
* existing quote to reset the flow.
|
|
23307
|
+
*/
|
|
23247
23308
|
const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription, setUpdatingChargeQuantityId, updatingChargeQuantityId, setErrorUpdatingQuantity, }) => {
|
|
23248
23309
|
// Context
|
|
23249
23310
|
const token = useToken();
|
|
@@ -23258,7 +23319,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23258
23319
|
const quote = readFragment(QuantityInput_QuoteFragment, maskedQuote);
|
|
23259
23320
|
// Hooks
|
|
23260
23321
|
const showErrorNotification = useErrorNotification();
|
|
23261
|
-
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
23322
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23262
23323
|
const quantityDisabled =
|
|
23263
23324
|
// If we are editing a quote, we disable the quantity input
|
|
23264
23325
|
// If we don't have a quantity, we disable the quantity input
|
|
@@ -23271,7 +23332,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23271
23332
|
!charge.selfServiceQuantity;
|
|
23272
23333
|
const value = quantity === undefined ? '' : quantity;
|
|
23273
23334
|
// Mutations
|
|
23274
|
-
const { mutate: createCharge } = useMutation({
|
|
23335
|
+
const { mutate: createCharge, isPending: isCreatingCharge } = useMutation({
|
|
23275
23336
|
mutationFn: quoteChargeCreate$1,
|
|
23276
23337
|
onSuccess: response => {
|
|
23277
23338
|
var _a, _b;
|
|
@@ -23286,7 +23347,23 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23286
23347
|
setErrorUpdatingQuantity(true);
|
|
23287
23348
|
},
|
|
23288
23349
|
});
|
|
23289
|
-
const
|
|
23350
|
+
const { mutate: deleteQuote, isPending: isDeletingQuote } = useMutation({
|
|
23351
|
+
mutationFn: quoteDelete,
|
|
23352
|
+
onSuccess: response => {
|
|
23353
|
+
var _a;
|
|
23354
|
+
const quoteId = (_a = response === null || response === void 0 ? void 0 : response.quote) === null || _a === void 0 ? void 0 : _a.id;
|
|
23355
|
+
if (!quoteId) {
|
|
23356
|
+
showErrorNotification('quoteId is required');
|
|
23357
|
+
return;
|
|
23358
|
+
}
|
|
23359
|
+
setQuoteQueryData(quoteId, null);
|
|
23360
|
+
setQuoteId(undefined);
|
|
23361
|
+
},
|
|
23362
|
+
onError: () => {
|
|
23363
|
+
setErrorUpdatingQuantity(true);
|
|
23364
|
+
},
|
|
23365
|
+
});
|
|
23366
|
+
const { mutate: createQuote, isPending: isCreatingQuote } = useMutation({
|
|
23290
23367
|
mutationFn: (subscriptionId) => quoteSubscriptionUpdate([subscriptionId], apiHost, token),
|
|
23291
23368
|
onSuccess: quote => {
|
|
23292
23369
|
var _a, _b, _c;
|
|
@@ -23314,7 +23391,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23314
23391
|
setErrorUpdatingQuantity(true);
|
|
23315
23392
|
},
|
|
23316
23393
|
});
|
|
23317
|
-
const updateQuoteCharge = useMutation({
|
|
23394
|
+
const { mutate: updateQuoteCharge, isPending: isUpdatingQuoteCharge } = useMutation({
|
|
23318
23395
|
mutationFn: ({ quoteChargeId, quantity, }) => {
|
|
23319
23396
|
if (!quoteChargeId)
|
|
23320
23397
|
throw new Error('quoteChargeId is required');
|
|
@@ -23336,26 +23413,35 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23336
23413
|
});
|
|
23337
23414
|
const onChangeQuantity = (value) => {
|
|
23338
23415
|
var _a;
|
|
23416
|
+
// Cancel all debounced functions first
|
|
23417
|
+
debouncedQuantityUpdate.cancel();
|
|
23418
|
+
debouncedDeleteQuote.cancel();
|
|
23339
23419
|
// Handle empty string - don't convert to 0, keep it as undefined
|
|
23340
23420
|
const quantity = value === '' ? undefined : isNaN(parseInt(value)) ? 0 : parseInt(value);
|
|
23341
23421
|
setQuantity(quantity);
|
|
23342
23422
|
if (quantity === undefined) {
|
|
23343
23423
|
setUpdatingChargeQuantityId(undefined);
|
|
23424
|
+
if (quoteId) {
|
|
23425
|
+
// Only delete the quote if it exists
|
|
23426
|
+
debouncedDeleteQuote(quoteId);
|
|
23427
|
+
}
|
|
23344
23428
|
}
|
|
23345
23429
|
else {
|
|
23346
23430
|
if (!(charge === null || charge === void 0 ? void 0 : charge.priceListChargeId)) {
|
|
23347
23431
|
showErrorNotification('Charge ID is not found');
|
|
23348
23432
|
return;
|
|
23349
23433
|
}
|
|
23350
|
-
//
|
|
23434
|
+
// Used to disable all other quantity inputs for this subscription
|
|
23351
23435
|
setUpdatingChargeQuantityId(getUpdatingChargeQuantityId(charge.priceListChargeId, subscription.id));
|
|
23352
23436
|
const quantityDelta = quantity - ((_a = charge.quantity) !== null && _a !== void 0 ? _a : 0);
|
|
23353
|
-
debouncedQuantityUpdate.
|
|
23354
|
-
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, quantity, subscription.id, quote, quoteId);
|
|
23437
|
+
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, subscription.id, quote, quoteId);
|
|
23355
23438
|
}
|
|
23356
23439
|
};
|
|
23357
|
-
const
|
|
23358
|
-
|
|
23440
|
+
const debouncedDeleteQuote = useCallback(lodashExports.debounce((quoteId) => {
|
|
23441
|
+
deleteQuote({ id: quoteId, apiHost, token });
|
|
23442
|
+
}, DEBOUNCE_TIME$1), []);
|
|
23443
|
+
const debouncedQuantityUpdate = useCallback(lodashExports.debounce((priceListChargeId, quantityDelta, subscriptionId, quote, quoteId) => {
|
|
23444
|
+
var _a;
|
|
23359
23445
|
if (quantityDelta === 0) {
|
|
23360
23446
|
setErrorUpdatingQuantity(true);
|
|
23361
23447
|
showErrorNotification('New quantity cannot be the same as current');
|
|
@@ -23363,37 +23449,22 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23363
23449
|
}
|
|
23364
23450
|
// If we are not editing a quote, we create a new one
|
|
23365
23451
|
if (quoteId === undefined) {
|
|
23366
|
-
createQuote
|
|
23452
|
+
createQuote(subscriptionId);
|
|
23367
23453
|
}
|
|
23368
23454
|
else {
|
|
23369
23455
|
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); });
|
|
23370
23456
|
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; });
|
|
23371
23457
|
if (quoteCharge) {
|
|
23372
|
-
updateQuoteCharge
|
|
23458
|
+
updateQuoteCharge({
|
|
23373
23459
|
quoteChargeId: quoteCharge.id,
|
|
23374
23460
|
quantity: quantityDelta,
|
|
23375
23461
|
});
|
|
23376
23462
|
}
|
|
23377
|
-
else {
|
|
23378
|
-
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; });
|
|
23379
|
-
if (!(subscriptionCharge === null || subscriptionCharge === void 0 ? void 0 : subscriptionCharge.id))
|
|
23380
|
-
throw new Error('subscriptionCharge id is required');
|
|
23381
|
-
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id))
|
|
23382
|
-
throw new Error('quoteChange id is required');
|
|
23383
|
-
createCharge({
|
|
23384
|
-
apiHost,
|
|
23385
|
-
quantity, // This is a new charge so use quantity instead of quantityDelta
|
|
23386
|
-
quoteChangeId: quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id,
|
|
23387
|
-
startDate: formatDateForApi(dayjs()),
|
|
23388
|
-
subscriptionChargeId: subscriptionCharge.id,
|
|
23389
|
-
token,
|
|
23390
|
-
});
|
|
23391
|
-
}
|
|
23392
23463
|
}
|
|
23393
23464
|
}, DEBOUNCE_TIME$1), []);
|
|
23394
|
-
return (
|
|
23395
|
-
|
|
23396
|
-
|
|
23465
|
+
return (jsxs(Fragment, { children: [jsx(Input, { className: "bunny-text-right", disabled: quantityDisabled, onChange: e => {
|
|
23466
|
+
onChangeQuantity(e.target.value);
|
|
23467
|
+
}, style: { width: '96px' }, value: value }), jsx(QuoteIsLoadingUpdater, { quoteIsPending: isCreatingCharge || isDeletingQuote || isCreatingQuote || isUpdatingQuoteCharge })] }));
|
|
23397
23468
|
};
|
|
23398
23469
|
|
|
23399
23470
|
const QuantityChangeGridRow_SubscriptionChargeFragment = t(`
|
|
@@ -23520,6 +23591,46 @@ function invalidateSubscriptionsQueryKeys(queryClient, token) {
|
|
|
23520
23591
|
});
|
|
23521
23592
|
}
|
|
23522
23593
|
|
|
23594
|
+
const [QuoteRecalculateTaxesProvider, useQuoteRecalculateTaxes$2] = createValueContext();
|
|
23595
|
+
|
|
23596
|
+
const mutation$8 = t(`
|
|
23597
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
23598
|
+
quoteRecalculateTaxes(id: $id) {
|
|
23599
|
+
quote {
|
|
23600
|
+
...QuantityDrawer_QuoteFragment
|
|
23601
|
+
id
|
|
23602
|
+
}
|
|
23603
|
+
errors
|
|
23604
|
+
}
|
|
23605
|
+
}
|
|
23606
|
+
`, [QuantityDrawer_QuoteFragment]);
|
|
23607
|
+
const quoteRecalculateTaxes$1 = async ({ quoteId, apiHost, token, }) => {
|
|
23608
|
+
var _a;
|
|
23609
|
+
const response = await execute(mutation$8, { apiHost, token }, { id: quoteId });
|
|
23610
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
23611
|
+
};
|
|
23612
|
+
|
|
23613
|
+
const useQuoteRecalculateTaxes$1 = () => {
|
|
23614
|
+
const token = useToken();
|
|
23615
|
+
const { apiHost } = useContext(BunnyContext);
|
|
23616
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23617
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = useMutation({
|
|
23618
|
+
mutationFn: async ({ quoteId }) => {
|
|
23619
|
+
return await quoteRecalculateTaxes$1({ quoteId, apiHost, token });
|
|
23620
|
+
},
|
|
23621
|
+
onSuccess: quote => {
|
|
23622
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
23623
|
+
throw new Error('Quote ID is undefined');
|
|
23624
|
+
}
|
|
23625
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
23626
|
+
},
|
|
23627
|
+
});
|
|
23628
|
+
return {
|
|
23629
|
+
quoteRecalculateTaxesMutation,
|
|
23630
|
+
isRecalculatingTaxes,
|
|
23631
|
+
};
|
|
23632
|
+
};
|
|
23633
|
+
|
|
23523
23634
|
const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23524
23635
|
const token = useToken();
|
|
23525
23636
|
const queryClient = useQueryClient();
|
|
@@ -23529,6 +23640,8 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23529
23640
|
const [payModalVisible, setPayModalVisible] = useState(false);
|
|
23530
23641
|
const [updatingChargeQuantityId, setUpdatingChargeQuantityId] = useState(undefined);
|
|
23531
23642
|
const quote = useQuoteQueryData(quoteId);
|
|
23643
|
+
// Context
|
|
23644
|
+
const onRecalculateTaxes = useQuoteRecalculateTaxes$2();
|
|
23532
23645
|
// Handlers
|
|
23533
23646
|
const onSuccess = () => {
|
|
23534
23647
|
setQuantityDrawerOpen(false);
|
|
@@ -23558,10 +23671,11 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23558
23671
|
const handleOpenCheckout = () => {
|
|
23559
23672
|
setPayModalVisible(true);
|
|
23560
23673
|
};
|
|
23561
|
-
return (jsxs(Fragment, { children: [jsx(QuantityChangeDrawerDesktop, { onClose: handleDrawerClose, open: quantityDrawerOpen, openCheckout: handleOpenCheckout, subscriptions: subscriptions, setUpdatingChargeQuantityId: setUpdatingChargeQuantityId, updatingChargeQuantityId: updatingChargeQuantityId }), jsx(Checkout, { onCancel: onCancel, onSuccess: onSuccess, onFail: onFail, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: false })] }));
|
|
23674
|
+
return (jsxs(Fragment, { children: [jsx(QuantityChangeDrawerDesktop, { onClose: handleDrawerClose, open: quantityDrawerOpen, openCheckout: handleOpenCheckout, subscriptions: subscriptions, setUpdatingChargeQuantityId: setUpdatingChargeQuantityId, updatingChargeQuantityId: updatingChargeQuantityId }), jsx(Checkout, { onCancel: onCancel, onSuccess: onSuccess, onFail: onFail, onRecalculateTaxes: onRecalculateTaxes, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: false })] }));
|
|
23562
23675
|
};
|
|
23563
23676
|
const QuantityDrawer = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23564
|
-
|
|
23677
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes$1();
|
|
23678
|
+
return (jsx(QuoteIdProvider, { children: jsx(QuoteIsLoadingProvider, { children: jsx(QuoteRecalculateTaxesProvider, { value: quoteId => quoteRecalculateTaxesMutation({ quoteId }), children: jsx(QuantityDrawerContent, { subscriptions: subscriptions, quantityDrawerOpen: quantityDrawerOpen, setQuantityDrawerOpen: setQuantityDrawerOpen, handlePortalErrors: handlePortalErrors, setShowInactive: setShowInactive }) }) }) }));
|
|
23565
23679
|
};
|
|
23566
23680
|
|
|
23567
23681
|
const useCancelSubscription = () => {
|
|
@@ -23825,14 +23939,27 @@ const SubscriptionCardActions = ({ onChangePlanClick, onCancelSubscriptionClick,
|
|
|
23825
23939
|
const isInTrial = isSubscriptionTrial(subscription);
|
|
23826
23940
|
const isTrialExpired = isSubscriptionTrialExpired(subscription);
|
|
23827
23941
|
const isActiveOrPending = isSubscriptionActiveOrPending(subscription);
|
|
23942
|
+
const getButtonLabel = () => {
|
|
23943
|
+
if (isInTrial) {
|
|
23944
|
+
return 'Upgrade from trial';
|
|
23945
|
+
}
|
|
23946
|
+
if (isTrialExpired) {
|
|
23947
|
+
return 'Upgrade';
|
|
23948
|
+
}
|
|
23949
|
+
// If the subscription is an addon, we should show the "Adjust plan" button since we don't support changing add-on plans.
|
|
23950
|
+
if (subscription.priceList.plan.addon === true) {
|
|
23951
|
+
return 'Adjust plan';
|
|
23952
|
+
}
|
|
23953
|
+
return 'Change plan';
|
|
23954
|
+
};
|
|
23828
23955
|
if (isPaymentMethodLoading)
|
|
23829
23956
|
return null;
|
|
23830
23957
|
return (jsxs(Fragment, { children: [isSelfServiceCancelable && onCancelSubscriptionClick && (isInTrial || isActiveOrPending) && (jsx(Popconfirm, { icon: null, onConfirm: () => onCancelSubscriptionClick(subscription), title: "Cancel subscription", children: jsx(Button, { className: "bunny-p-0", type: "link", children: "Cancel subscription" }) })), arePlansAvailable &&
|
|
23831
23958
|
onChangePlanClick &&
|
|
23832
|
-
(isActiveOrPending || isInTrial || isTrialExpired) && (jsx(Button, { onClick: () => onChangePlanClick(subscription), type: 'primary', children:
|
|
23959
|
+
(isActiveOrPending || isInTrial || isTrialExpired) && (jsx(Button, { onClick: () => onChangePlanClick(subscription), type: 'primary', children: getButtonLabel() })), !arePlansAvailable && isInTrial && jsx(Tag, { color: "warning", children: "Cannot upgrade" })] }));
|
|
23833
23960
|
};
|
|
23834
23961
|
|
|
23835
|
-
const query$
|
|
23962
|
+
const query$4 = t(`
|
|
23836
23963
|
query priceListChangeOptions($productId: ID!) {
|
|
23837
23964
|
priceListChangeOptions(productId: $productId) {
|
|
23838
23965
|
...SubscriptionCardActions_PriceListChangeOptionsFragment
|
|
@@ -23840,7 +23967,7 @@ const query$2 = t(`
|
|
|
23840
23967
|
}
|
|
23841
23968
|
`, [SubscriptionCardActions_PriceListChangeOptionsFragment]);
|
|
23842
23969
|
const getPriceListChangeOptions$1 = async ({ apiHost, productId, token, }) => {
|
|
23843
|
-
const response = await execute(query$
|
|
23970
|
+
const response = await execute(query$4, { apiHost, token }, { productId });
|
|
23844
23971
|
return response.priceListChangeOptions;
|
|
23845
23972
|
};
|
|
23846
23973
|
|
|
@@ -23874,7 +24001,7 @@ const getSubscriptionStatusText = (subscription) => {
|
|
|
23874
24001
|
return `Trial expires on ${formatDate(trialEndDate)}`;
|
|
23875
24002
|
}
|
|
23876
24003
|
}
|
|
23877
|
-
if (evergreen) {
|
|
24004
|
+
if (evergreen && subscription.state === t.scalar('SubscriptionState', 'ACTIVE')) {
|
|
23878
24005
|
return `Renews on ${formatDate(endDate)}`;
|
|
23879
24006
|
}
|
|
23880
24007
|
return `Ends on ${formatDate(endDate || trialEndDate)}`;
|
|
@@ -23952,40 +24079,66 @@ const formatNumber = (num, decimals = 2) => {
|
|
|
23952
24079
|
});
|
|
23953
24080
|
};
|
|
23954
24081
|
|
|
24082
|
+
const getPricingModelDescription = (pricingModel) => {
|
|
24083
|
+
switch (pricingModel) {
|
|
24084
|
+
case 'TIERED':
|
|
24085
|
+
return 'units in each tier are priced separately.';
|
|
24086
|
+
case 'VOLUME':
|
|
24087
|
+
return 'the highest tier reached prices all units.';
|
|
24088
|
+
case 'BANDS':
|
|
24089
|
+
return 'the quantity indexes to a flat price.';
|
|
24090
|
+
default:
|
|
24091
|
+
return '';
|
|
24092
|
+
}
|
|
24093
|
+
};
|
|
24094
|
+
|
|
24095
|
+
const getPricingModelTitle = (pricingModel) => {
|
|
24096
|
+
switch (pricingModel) {
|
|
24097
|
+
case 'TIERED':
|
|
24098
|
+
return 'Tiered';
|
|
24099
|
+
case 'VOLUME':
|
|
24100
|
+
return 'Volume';
|
|
24101
|
+
case 'BANDS':
|
|
24102
|
+
return 'Bands';
|
|
24103
|
+
default:
|
|
24104
|
+
return '';
|
|
24105
|
+
}
|
|
24106
|
+
};
|
|
24107
|
+
|
|
23955
24108
|
const StyledTable = styled(Table) `
|
|
23956
24109
|
.ant-table-cell {
|
|
23957
24110
|
border-bottom: none !important;
|
|
23958
24111
|
}
|
|
23959
24112
|
`;
|
|
23960
|
-
const TieredDisplayDropdown = ({ priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
24113
|
+
const TieredDisplayDropdown = ({ pricingModel, priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
23961
24114
|
const onlyHasOneTier = (priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers.length) === 1;
|
|
23962
24115
|
const dropdownTrigger = (jsx("div", { className: `w-full ${onlyHasOneTier ? '' : 'underline cursor-pointer'}`, children: truncatedText }));
|
|
23963
24116
|
if (onlyHasOneTier) {
|
|
23964
24117
|
return dropdownTrigger;
|
|
23965
24118
|
}
|
|
23966
24119
|
return (jsx(Dropdown, { popupRender: () => {
|
|
23967
|
-
return (
|
|
23968
|
-
|
|
23969
|
-
|
|
23970
|
-
|
|
23971
|
-
|
|
23972
|
-
|
|
23973
|
-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
24120
|
+
return (jsxs("div", { className: "rounded border border-solid border-slate-200 bg-white overflow-hidden", children: [jsxs("div", { className: "bunny-text-gray-400 bunny-p-2", children: [getPricingModelTitle(pricingModel), " pricing -", ' ', getPricingModelDescription(pricingModel)] }), jsx(StyledTable, { columns: [
|
|
24121
|
+
{
|
|
24122
|
+
dataIndex: 'starts',
|
|
24123
|
+
title: 'From # of units',
|
|
24124
|
+
align: 'right',
|
|
24125
|
+
render: (_, record, index) => {
|
|
24126
|
+
record = record;
|
|
24127
|
+
const nextRecord = priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers[index + 1];
|
|
24128
|
+
const starts = record.starts;
|
|
24129
|
+
const ends = (nextRecord === null || nextRecord === void 0 ? void 0 : nextRecord.starts) ? nextRecord.starts - 1 : '+';
|
|
24130
|
+
return (jsxs(Fragment, { children: [formatNumber(starts, 0), typeof ends === 'number' ? formatNumber(ends, 0) : '+'] }));
|
|
24131
|
+
},
|
|
23978
24132
|
},
|
|
23979
|
-
|
|
23980
|
-
|
|
23981
|
-
|
|
23982
|
-
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
|
|
24133
|
+
{
|
|
24134
|
+
dataIndex: 'price',
|
|
24135
|
+
title: 'Unit price',
|
|
24136
|
+
align: 'right',
|
|
24137
|
+
render: value => {
|
|
24138
|
+
return jsx(Fragment, { children: formatCurrency$1(value, currencyId, priceDecimals) });
|
|
24139
|
+
},
|
|
23986
24140
|
},
|
|
23987
|
-
}
|
|
23988
|
-
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" }) }));
|
|
24141
|
+
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" })] }));
|
|
23989
24142
|
}, children: dropdownTrigger }));
|
|
23990
24143
|
};
|
|
23991
24144
|
|
|
@@ -24036,7 +24189,7 @@ const SubscriptionChargeUnitPrice = ({ charge, currencyId, }) => {
|
|
|
24036
24189
|
? '-'
|
|
24037
24190
|
: formatCurrency$1(charge.discountedPrice, currencyId, charge.priceDecimals);
|
|
24038
24191
|
const isChargeDiscount = isDiscount$1(charge.kind);
|
|
24039
|
-
return (jsx(Fragment, { children: hasPriceTiers(charge) ? (jsx(TieredDisplayDropdown, { priceTiers: charge.priceTiers, currencyId: currencyId, priceDecimals: charge.priceDecimals, truncatedText: `${charge.kind === QuoteChangeKind.PRICE_UPDATE ? 'new ' : ''}${getApplicablePriceTier(charge, currencyId, charge.priceDecimals)}` })) : isChargeDiscount ? (`-${price}`) : (price) }));
|
|
24192
|
+
return (jsx(Fragment, { children: hasPriceTiers(charge) ? (jsx(TieredDisplayDropdown, { pricingModel: charge.pricingModel, priceTiers: charge.priceTiers, currencyId: currencyId, priceDecimals: charge.priceDecimals, truncatedText: `${charge.kind === QuoteChangeKind.PRICE_UPDATE ? 'new ' : ''}${getApplicablePriceTier(charge, currencyId, charge.priceDecimals)}` })) : isChargeDiscount ? (`-${price}`) : (price) }));
|
|
24040
24193
|
};
|
|
24041
24194
|
|
|
24042
24195
|
const { Text: Text$e } = Typography;
|
|
@@ -24173,7 +24326,7 @@ const SubscriptionCardDesktopRow = ({ charge, chargeIndex, charges, currencyId,
|
|
|
24173
24326
|
: (_b = charge.quantity) === null || _b === void 0 ? void 0 : _b.toLocaleString() }), jsx(SubscriptionsListCell, { right: true, children: jsx(SubscriptionChargeUnitPrice, { charge: charge, currencyId: currencyId }) }), jsx(SubscriptionsListCell, { right: true, children: jsx(SubscriptionChargeTotal, { charge: charge, currencyId: currencyId }) })] }));
|
|
24174
24327
|
};
|
|
24175
24328
|
|
|
24176
|
-
function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, subscription, showInactive, }) {
|
|
24329
|
+
function AddonSubscriptionsCards({ onCancelSubscriptionClick, onChangePlanClick, subscriptions, subscription, showInactive, }) {
|
|
24177
24330
|
const addonSubscriptions = findAddonSubscriptions(subscription, subscriptions);
|
|
24178
24331
|
if (addonSubscriptions.length === 0) {
|
|
24179
24332
|
return null;
|
|
@@ -24182,7 +24335,7 @@ function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, sub
|
|
|
24182
24335
|
if (!showInactive && isSubscriptionNotActive(addonSubscription))
|
|
24183
24336
|
return null;
|
|
24184
24337
|
const isLast = addonSubscriptionIndex === addonSubscriptions.length - 1;
|
|
24185
|
-
return (jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsx(AddonIndentation, { isLast: isLast, indentation: ADDON_INDENTATION, verticalMargin: "-1rem" }), jsx("div", { className: "bunny-flex-1", children: jsx(SubscriptionCardDesktop, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: addonSubscription, isAddon: true }) })] }, addonSubscriptionIndex));
|
|
24338
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsx(AddonIndentation, { isLast: isLast, indentation: ADDON_INDENTATION, verticalMargin: "-1rem" }), jsx("div", { className: "bunny-flex-1", children: jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: addonSubscription, isAddon: true }) })] }, addonSubscriptionIndex));
|
|
24186
24339
|
}) }));
|
|
24187
24340
|
}
|
|
24188
24341
|
|
|
@@ -24241,8 +24394,8 @@ const SubscriptionsList = ({ showInactive, onChangePlanClick, onCancelSubscripti
|
|
|
24241
24394
|
if (!showInactive && isSubscriptionNotActive(subscription))
|
|
24242
24395
|
return null;
|
|
24243
24396
|
if (isMobile)
|
|
24244
|
-
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsx(SubscriptionCard, { subscription: subscription }), jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24245
|
-
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription }), jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24397
|
+
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsx(SubscriptionCard, { subscription: subscription }), jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, onChangePlanClick: onChangePlanClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24398
|
+
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription }), jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, onChangePlanClick: onChangePlanClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24246
24399
|
}) }));
|
|
24247
24400
|
};
|
|
24248
24401
|
|
|
@@ -24313,7 +24466,7 @@ const FormattedQuoteFields_QuoteFragment = t(`
|
|
|
24313
24466
|
}
|
|
24314
24467
|
}
|
|
24315
24468
|
`);
|
|
24316
|
-
const query$
|
|
24469
|
+
const query$3 = t(`
|
|
24317
24470
|
query quote($id: ID, $includeHtmlField: Boolean!) {
|
|
24318
24471
|
quote(id: $id) {
|
|
24319
24472
|
...FormattedQuoteFields_QuoteFragment @include(if: $includeHtmlField)
|
|
@@ -24322,7 +24475,7 @@ const query$1 = t(`
|
|
|
24322
24475
|
}
|
|
24323
24476
|
`, [FormattedQuoteFields_QuoteFragment, QuoteContext_QuoteFragment]);
|
|
24324
24477
|
const getQuote = async ({ id, token, apiHost, includeHtmlField = false, }) => {
|
|
24325
|
-
const response = await execute(query$
|
|
24478
|
+
const response = await execute(query$3, { apiHost, token }, { id, includeHtmlField });
|
|
24326
24479
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
24327
24480
|
};
|
|
24328
24481
|
|
|
@@ -24427,7 +24580,7 @@ const calculateNewQuantity = (priceListCharge, currentQuantity = 1) => {
|
|
|
24427
24580
|
return quantityMin;
|
|
24428
24581
|
};
|
|
24429
24582
|
|
|
24430
|
-
const mutation$
|
|
24583
|
+
const mutation$7 = t(`
|
|
24431
24584
|
mutation QuoteChangeUpdate($id: ID!, $charges: [QuoteChargeAttributes!]!) {
|
|
24432
24585
|
quoteChangeUpdate(id: $id, charges: $charges) {
|
|
24433
24586
|
quoteChange {
|
|
@@ -24441,7 +24594,7 @@ const mutation$1 = t(`
|
|
|
24441
24594
|
`, [QuoteContext_QuoteFragment]);
|
|
24442
24595
|
const quoteChangeUpdate = async ({ quoteChangeId, charges, apiHost, token, }) => {
|
|
24443
24596
|
var _a, _b;
|
|
24444
|
-
const response = await execute(mutation$
|
|
24597
|
+
const response = await execute(mutation$7, {
|
|
24445
24598
|
apiHost,
|
|
24446
24599
|
token,
|
|
24447
24600
|
}, {
|
|
@@ -24497,6 +24650,19 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24497
24650
|
};
|
|
24498
24651
|
}
|
|
24499
24652
|
|
|
24653
|
+
const useSetQuoteQueryData = () => {
|
|
24654
|
+
const token = useToken();
|
|
24655
|
+
const queryClient = useQueryClient();
|
|
24656
|
+
const setQuoteQueryData = (quoteId, quote) => {
|
|
24657
|
+
queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
|
|
24658
|
+
id: quoteId,
|
|
24659
|
+
objectName: 'editingQuote',
|
|
24660
|
+
token,
|
|
24661
|
+
}), quote);
|
|
24662
|
+
};
|
|
24663
|
+
return { setQuoteQueryData };
|
|
24664
|
+
};
|
|
24665
|
+
|
|
24500
24666
|
// Functionality:
|
|
24501
24667
|
// 1: keep track of quantities set for features based on feature.id
|
|
24502
24668
|
// a. copy those quantities over to charges with same feature when initializing
|
|
@@ -24509,9 +24675,9 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24509
24675
|
const showErrorNotification = useErrorNotification();
|
|
24510
24676
|
const DEBOUNCE_TIME = 1000;
|
|
24511
24677
|
const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
24512
|
-
const queryClient = useQueryClient();
|
|
24513
24678
|
const token = useToken();
|
|
24514
24679
|
const { apiHost } = useContext(BunnyContext);
|
|
24680
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24515
24681
|
// Derived state
|
|
24516
24682
|
const selectedPriceListQuoteChange = useMemo(() => {
|
|
24517
24683
|
var _a;
|
|
@@ -24530,23 +24696,27 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24530
24696
|
});
|
|
24531
24697
|
},
|
|
24532
24698
|
onSuccess: quoteChange => {
|
|
24533
|
-
|
|
24534
|
-
|
|
24535
|
-
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
}
|
|
24699
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24700
|
+
throw new Error('Quote ID is undefined');
|
|
24701
|
+
}
|
|
24702
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote)) {
|
|
24703
|
+
throw new Error('Quote is undefined');
|
|
24704
|
+
}
|
|
24705
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote);
|
|
24539
24706
|
},
|
|
24540
24707
|
});
|
|
24541
24708
|
function handleUpdateQuoteQuantities(featureQuantities) {
|
|
24542
24709
|
if (!selectedPriceListQuoteChange) {
|
|
24543
|
-
|
|
24710
|
+
console.error('Quote change is undefined');
|
|
24711
|
+
return;
|
|
24544
24712
|
}
|
|
24545
24713
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24546
|
-
|
|
24714
|
+
console.error('Quote ID is undefined');
|
|
24715
|
+
return;
|
|
24547
24716
|
}
|
|
24548
24717
|
if (!(selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.id)) {
|
|
24549
|
-
|
|
24718
|
+
console.error('Quote change ID is undefined');
|
|
24719
|
+
return;
|
|
24550
24720
|
}
|
|
24551
24721
|
const featureIdsToUpdate = Object.keys(featureQuantities).filter(featureId => {
|
|
24552
24722
|
// If the quantities differ, then update quote with the quantities present in useFeatureQuantities
|
|
@@ -24558,20 +24728,24 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24558
24728
|
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; });
|
|
24559
24729
|
return quoteCharge !== undefined && localAndQuoteQuantitiesDiffer;
|
|
24560
24730
|
});
|
|
24561
|
-
const charges = featureIdsToUpdate
|
|
24731
|
+
const charges = featureIdsToUpdate
|
|
24732
|
+
.map(featureId => {
|
|
24562
24733
|
const quoteCharge = selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.charges.find(charge => { var _a; return ((_a = charge === null || charge === void 0 ? void 0 : charge.feature) === null || _a === void 0 ? void 0 : _a.id) === featureId; });
|
|
24563
24734
|
const quantity = getFeatureQuantity(featureId, featureQuantities);
|
|
24564
24735
|
if (!quantity) {
|
|
24565
|
-
|
|
24736
|
+
console.error('Quantity is undefined');
|
|
24737
|
+
return;
|
|
24566
24738
|
}
|
|
24567
24739
|
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id)) {
|
|
24568
|
-
|
|
24740
|
+
console.error('Quote charge for featureId is undefined');
|
|
24741
|
+
return;
|
|
24569
24742
|
}
|
|
24570
24743
|
return {
|
|
24571
24744
|
id: quoteCharge.id,
|
|
24572
24745
|
quantity: quantity,
|
|
24573
24746
|
};
|
|
24574
|
-
})
|
|
24747
|
+
})
|
|
24748
|
+
.filter(charge => charge !== undefined);
|
|
24575
24749
|
if (charges.length === 0) {
|
|
24576
24750
|
return;
|
|
24577
24751
|
}
|
|
@@ -24639,6 +24813,44 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24639
24813
|
};
|
|
24640
24814
|
};
|
|
24641
24815
|
|
|
24816
|
+
const mutation$6 = t(`
|
|
24817
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
24818
|
+
quoteRecalculateTaxes(id: $id) {
|
|
24819
|
+
quote {
|
|
24820
|
+
...QuoteContext_QuoteFragment
|
|
24821
|
+
id
|
|
24822
|
+
}
|
|
24823
|
+
errors
|
|
24824
|
+
}
|
|
24825
|
+
}
|
|
24826
|
+
`, [QuoteContext_QuoteFragment]);
|
|
24827
|
+
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
24828
|
+
var _a;
|
|
24829
|
+
const response = await execute(mutation$6, { apiHost, token }, { id: quoteId });
|
|
24830
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
24831
|
+
};
|
|
24832
|
+
|
|
24833
|
+
const useQuoteRecalculateTaxes = () => {
|
|
24834
|
+
const token = useToken();
|
|
24835
|
+
const { apiHost } = useContext(BunnyContext);
|
|
24836
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24837
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = useMutation({
|
|
24838
|
+
mutationFn: async ({ quoteId }) => {
|
|
24839
|
+
return await quoteRecalculateTaxes({ quoteId, apiHost, token });
|
|
24840
|
+
},
|
|
24841
|
+
onSuccess: quote => {
|
|
24842
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24843
|
+
throw new Error('Quote ID is undefined');
|
|
24844
|
+
}
|
|
24845
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
24846
|
+
},
|
|
24847
|
+
});
|
|
24848
|
+
return {
|
|
24849
|
+
quoteRecalculateTaxesMutation,
|
|
24850
|
+
isRecalculatingTaxes,
|
|
24851
|
+
};
|
|
24852
|
+
};
|
|
24853
|
+
|
|
24642
24854
|
function useFeatureAddonsPending() {
|
|
24643
24855
|
const [featureAddonsLoading, setFeatureAddonsLoading] = useState([]);
|
|
24644
24856
|
const addFeatureAddonLoading = (featureAddonId) => {
|
|
@@ -24662,6 +24874,7 @@ function QuoteProvider({ children }) {
|
|
|
24662
24874
|
// Hooks
|
|
24663
24875
|
const token = useToken();
|
|
24664
24876
|
const { isFeatureAddonsLoading, addFeatureAddonLoading, removeFeatureAddonLoading } = useFeatureAddonsPending();
|
|
24877
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes();
|
|
24665
24878
|
const { quote: maskedQuote, isQuotePending } = useQuoteCreate({
|
|
24666
24879
|
upgradingSubscription,
|
|
24667
24880
|
selectedPriceList: selectedPriceList,
|
|
@@ -24697,6 +24910,7 @@ function QuoteProvider({ children }) {
|
|
|
24697
24910
|
onChangeSelectedPriceList: handleChangeSelectedPriceList,
|
|
24698
24911
|
onChangeQuantity,
|
|
24699
24912
|
getFeatureQuantity,
|
|
24913
|
+
onRecalculateTaxes: (id) => quoteRecalculateTaxesMutation({ quoteId: id }),
|
|
24700
24914
|
}, children: children }));
|
|
24701
24915
|
}
|
|
24702
24916
|
|
|
@@ -24723,40 +24937,6 @@ function priceDescriptionString({ unitName, showPriceAsMonthly, periodMonths, pr
|
|
|
24723
24937
|
return `Per ${unitName && !priceListHasFlatFeeCharges ? `${unitName.toLowerCase()} / ` : ''}${showPriceAsMonthly ? 'month' : periodLabel}`;
|
|
24724
24938
|
}
|
|
24725
24939
|
|
|
24726
|
-
var localizedFormat$2 = {exports: {}};
|
|
24727
|
-
|
|
24728
|
-
var localizedFormat$1 = localizedFormat$2.exports;
|
|
24729
|
-
|
|
24730
|
-
var hasRequiredLocalizedFormat;
|
|
24731
|
-
|
|
24732
|
-
function requireLocalizedFormat () {
|
|
24733
|
-
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
24734
|
-
hasRequiredLocalizedFormat = 1;
|
|
24735
|
-
(function (module, exports) {
|
|
24736
|
-
!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)};}}));
|
|
24737
|
-
} (localizedFormat$2));
|
|
24738
|
-
return localizedFormat$2.exports;
|
|
24739
|
-
}
|
|
24740
|
-
|
|
24741
|
-
var localizedFormatExports = requireLocalizedFormat();
|
|
24742
|
-
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
24743
|
-
|
|
24744
|
-
dayjs.extend(localizedFormat);
|
|
24745
|
-
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
24746
|
-
if (value !== 0 && !value)
|
|
24747
|
-
return '';
|
|
24748
|
-
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
24749
|
-
if (isNaN(currencyValue))
|
|
24750
|
-
return value;
|
|
24751
|
-
const localeOptions = {
|
|
24752
|
-
minimumFractionDigits: decimals,
|
|
24753
|
-
maximumFractionDigits: decimals,
|
|
24754
|
-
};
|
|
24755
|
-
localeOptions.style = 'currency';
|
|
24756
|
-
localeOptions.currency = currencyIsoCode;
|
|
24757
|
-
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
24758
|
-
};
|
|
24759
|
-
|
|
24760
24940
|
const { Text: Text$b } = Typography;
|
|
24761
24941
|
const PriceTierPrice = ({ currencyId, priceDecimals, tier, }) => {
|
|
24762
24942
|
return (jsx(Text$b, { className: "bunny-text-white", children: formatCurrency(tier.price, currencyId, priceDecimals) }));
|
|
@@ -24780,32 +24960,6 @@ const PriceTierRow = ({ tier: maskedTier, nextTier: maskedNextTier, }) => {
|
|
|
24780
24960
|
return jsx(Text$a, { className: "bunny-text-white", children: text });
|
|
24781
24961
|
};
|
|
24782
24962
|
|
|
24783
|
-
const getPricingModelTitle = (pricingModel) => {
|
|
24784
|
-
switch (pricingModel) {
|
|
24785
|
-
case 'TIERED':
|
|
24786
|
-
return 'Tiered';
|
|
24787
|
-
case 'VOLUME':
|
|
24788
|
-
return 'Volume';
|
|
24789
|
-
case 'BANDS':
|
|
24790
|
-
return 'Bands';
|
|
24791
|
-
default:
|
|
24792
|
-
return '';
|
|
24793
|
-
}
|
|
24794
|
-
};
|
|
24795
|
-
|
|
24796
|
-
const getPricingModelDescription = (pricingModel) => {
|
|
24797
|
-
switch (pricingModel) {
|
|
24798
|
-
case 'TIERED':
|
|
24799
|
-
return 'units in each tier are priced separately.';
|
|
24800
|
-
case 'VOLUME':
|
|
24801
|
-
return 'the highest tier reached prices all units.';
|
|
24802
|
-
case 'BANDS':
|
|
24803
|
-
return 'the quantity indexes to a flat price.';
|
|
24804
|
-
default:
|
|
24805
|
-
return '';
|
|
24806
|
-
}
|
|
24807
|
-
};
|
|
24808
|
-
|
|
24809
24963
|
const { Text: Text$9 } = Typography;
|
|
24810
24964
|
const ChargePriceTiers_PriceListChargeFragment = t(`
|
|
24811
24965
|
fragment ChargePriceTiers_PriceListChargeFragment on PriceListCharge {
|
|
@@ -25440,57 +25594,13 @@ const getAvailablePlansAndPriceLists = ({ availablePriceLists, priceListChangeOp
|
|
|
25440
25594
|
return {
|
|
25441
25595
|
availablePriceListsArray,
|
|
25442
25596
|
displayPriceLists,
|
|
25443
|
-
};
|
|
25444
|
-
};
|
|
25445
|
-
const everythingInPlusString = ({ priceList }) => {
|
|
25446
|
-
return `Everything in ${priceList.plan.name}, plus`;
|
|
25447
|
-
};
|
|
25448
|
-
|
|
25449
|
-
const QUOTE_CHARGE_CREATE = `
|
|
25450
|
-
${QUOTE_FIELDS()}
|
|
25451
|
-
mutation QuoteChargeCreate ($quoteChangeId: ID!, $startDate: ISO8601Date!, $endDate: ISO8601Date, $priceListChargeId: ID, $subscriptionChargeId: ID, $price: Float, $quantity: Int) {
|
|
25452
|
-
quoteChargeCreate(
|
|
25453
|
-
endDate: $endDate
|
|
25454
|
-
price: $price
|
|
25455
|
-
priceListChargeId: $priceListChargeId
|
|
25456
|
-
quantity: $quantity
|
|
25457
|
-
quoteChangeId: $quoteChangeId
|
|
25458
|
-
startDate: $startDate
|
|
25459
|
-
subscriptionChargeId: $subscriptionChargeId
|
|
25460
|
-
) {
|
|
25461
|
-
quoteCharge {
|
|
25462
|
-
quoteChange {
|
|
25463
|
-
id
|
|
25464
|
-
quoteId
|
|
25465
|
-
quote {
|
|
25466
|
-
...QuoteFields
|
|
25467
|
-
}
|
|
25468
|
-
}
|
|
25469
|
-
id
|
|
25470
|
-
}
|
|
25471
|
-
}
|
|
25472
|
-
}
|
|
25473
|
-
|
|
25474
|
-
`;
|
|
25475
|
-
const quoteChargeCreate = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
25476
|
-
var _a;
|
|
25477
|
-
const response = await gqlRequest({
|
|
25478
|
-
query: QUOTE_CHARGE_CREATE,
|
|
25479
|
-
vars: {
|
|
25480
|
-
price,
|
|
25481
|
-
priceListChargeId,
|
|
25482
|
-
quantity,
|
|
25483
|
-
quoteChangeId,
|
|
25484
|
-
startDate,
|
|
25485
|
-
subscriptionChargeId,
|
|
25486
|
-
},
|
|
25487
|
-
apiHost,
|
|
25488
|
-
token,
|
|
25489
|
-
});
|
|
25490
|
-
return (_a = response === null || response === void 0 ? void 0 : response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
25597
|
+
};
|
|
25598
|
+
};
|
|
25599
|
+
const everythingInPlusString = ({ priceList }) => {
|
|
25600
|
+
return `Everything in ${priceList.plan.name}, plus`;
|
|
25491
25601
|
};
|
|
25492
25602
|
|
|
25493
|
-
const mutation = t(`
|
|
25603
|
+
const mutation$5 = t(`
|
|
25494
25604
|
mutation QuoteChargeDelete($quoteChargeId: ID!) {
|
|
25495
25605
|
quoteChargeDelete(quoteChargeId: $quoteChargeId) {
|
|
25496
25606
|
errors
|
|
@@ -25508,21 +25618,76 @@ const mutation = t(`
|
|
|
25508
25618
|
`, [QuoteContext_QuoteFragment]);
|
|
25509
25619
|
const quoteChargeDelete = async ({ quoteChargeId, token, apiHost }) => {
|
|
25510
25620
|
var _a, _b, _c, _d;
|
|
25511
|
-
const response = await execute(mutation, { apiHost, token }, { quoteChargeId });
|
|
25621
|
+
const response = await execute(mutation$5, { apiHost, token }, { quoteChargeId });
|
|
25512
25622
|
if ((_a = response.quoteChargeDelete) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
25513
25623
|
throw new Error((_c = (_b = response.quoteChargeDelete) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c[0]);
|
|
25514
25624
|
}
|
|
25515
25625
|
return (_d = response.quoteChargeDelete) === null || _d === void 0 ? void 0 : _d.quoteCharge;
|
|
25516
25626
|
};
|
|
25517
25627
|
|
|
25518
|
-
const
|
|
25628
|
+
const mutation$4 = t(`
|
|
25629
|
+
mutation QuoteChargeCreate(
|
|
25630
|
+
$quoteChangeId: ID!
|
|
25631
|
+
$startDate: ISO8601Date!
|
|
25632
|
+
$endDate: ISO8601Date
|
|
25633
|
+
$priceListChargeId: ID
|
|
25634
|
+
$subscriptionChargeId: ID
|
|
25635
|
+
$price: Float
|
|
25636
|
+
$quantity: Int
|
|
25637
|
+
) {
|
|
25638
|
+
quoteChargeCreate(
|
|
25639
|
+
endDate: $endDate
|
|
25640
|
+
price: $price
|
|
25641
|
+
priceListChargeId: $priceListChargeId
|
|
25642
|
+
quantity: $quantity
|
|
25643
|
+
quoteChangeId: $quoteChangeId
|
|
25644
|
+
startDate: $startDate
|
|
25645
|
+
subscriptionChargeId: $subscriptionChargeId
|
|
25646
|
+
) {
|
|
25647
|
+
quoteCharge {
|
|
25648
|
+
quoteChange {
|
|
25649
|
+
id
|
|
25650
|
+
quoteId
|
|
25651
|
+
quote {
|
|
25652
|
+
...QuoteContext_QuoteFragment
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
id
|
|
25656
|
+
}
|
|
25657
|
+
}
|
|
25658
|
+
}
|
|
25659
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25660
|
+
const quoteChargeCreate = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
25661
|
+
var _a;
|
|
25662
|
+
const response = await execute(mutation$4, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
25663
|
+
return (_a = response === null || response === void 0 ? void 0 : response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
25664
|
+
};
|
|
25665
|
+
|
|
25666
|
+
const useQuoteUpdateFeatureAddon = (maskedQuote, featureAddon) => {
|
|
25519
25667
|
const { apiHost } = useContext(BunnyContext);
|
|
25520
25668
|
const { addFeatureAddonLoading, removeFeatureAddonLoading } = useContext(QuoteContext);
|
|
25521
25669
|
const token = useToken();
|
|
25522
|
-
const
|
|
25670
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
25671
|
+
// Read fragments
|
|
25672
|
+
const quote = readFragment(useQuoteUpdateFeatureAddon_QuoteFragment, maskedQuote);
|
|
25523
25673
|
const addedQuoteChargeId = useRef();
|
|
25524
25674
|
function handleAddFeatureAddon() {
|
|
25525
|
-
|
|
25675
|
+
if (!token)
|
|
25676
|
+
throw new Error('Token is required');
|
|
25677
|
+
if (!quote)
|
|
25678
|
+
throw new Error('Editing quote is required');
|
|
25679
|
+
const quoteChangeId = findQuoteChangeForFeatureAddon(quote);
|
|
25680
|
+
if (!quoteChangeId)
|
|
25681
|
+
throw new Error('No available quote change for feature add-on');
|
|
25682
|
+
console.log('quote', quote);
|
|
25683
|
+
console.log('startDate', quote === null || quote === void 0 ? void 0 : quote.startDate);
|
|
25684
|
+
quoteChargeCreateMutation({
|
|
25685
|
+
quoteChangeId: quoteChangeId.id,
|
|
25686
|
+
priceListChargeId: featureAddon.id,
|
|
25687
|
+
startDate: quote === null || quote === void 0 ? void 0 : quote.startDate,
|
|
25688
|
+
apiHost,
|
|
25689
|
+
token,
|
|
25690
|
+
});
|
|
25526
25691
|
}
|
|
25527
25692
|
function handleRemoveFeatureAddon() {
|
|
25528
25693
|
if (!addedQuoteChargeId.current)
|
|
@@ -25530,30 +25695,16 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25530
25695
|
quoteChargeDeleteMutation({ quoteChargeId: addedQuoteChargeId.current });
|
|
25531
25696
|
}
|
|
25532
25697
|
const { mutate: quoteChargeCreateMutation, isPending: isCreatingFeatureAddon } = useMutation({
|
|
25533
|
-
mutationFn:
|
|
25534
|
-
|
|
25535
|
-
|
|
25536
|
-
if (!quote)
|
|
25537
|
-
throw new Error('
|
|
25538
|
-
|
|
25539
|
-
if (!
|
|
25540
|
-
throw new Error('
|
|
25541
|
-
|
|
25542
|
-
|
|
25543
|
-
priceListChargeId: featureAddon.id,
|
|
25544
|
-
startDate: quote === null || quote === void 0 ? void 0 : quote.startDate,
|
|
25545
|
-
apiHost,
|
|
25546
|
-
token,
|
|
25547
|
-
});
|
|
25548
|
-
return { quoteCharge };
|
|
25549
|
-
},
|
|
25550
|
-
onSuccess: ({ quoteCharge }) => {
|
|
25551
|
-
addedQuoteChargeId.current = quoteCharge.id;
|
|
25552
|
-
queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
|
|
25553
|
-
objectName: 'editingQuote',
|
|
25554
|
-
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
25555
|
-
token,
|
|
25556
|
-
}), quoteCharge.quoteChange.quote);
|
|
25698
|
+
mutationFn: quoteChargeCreate,
|
|
25699
|
+
onSuccess: quoteCharge => {
|
|
25700
|
+
addedQuoteChargeId.current = quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id;
|
|
25701
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25702
|
+
throw new Error('Quote ID is undefined');
|
|
25703
|
+
}
|
|
25704
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25705
|
+
throw new Error('Quote is undefined');
|
|
25706
|
+
}
|
|
25707
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25557
25708
|
},
|
|
25558
25709
|
});
|
|
25559
25710
|
const { mutate: quoteChargeDeleteMutation, isPending: isDeletingFeatureAddon } = useMutation({
|
|
@@ -25563,11 +25714,13 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25563
25714
|
},
|
|
25564
25715
|
onSuccess: quoteCharge => {
|
|
25565
25716
|
addedQuoteChargeId.current = undefined;
|
|
25566
|
-
|
|
25567
|
-
|
|
25568
|
-
|
|
25569
|
-
|
|
25570
|
-
|
|
25717
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25718
|
+
throw new Error('Quote ID is undefined');
|
|
25719
|
+
}
|
|
25720
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25721
|
+
throw new Error('Quote is undefined');
|
|
25722
|
+
}
|
|
25723
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25571
25724
|
},
|
|
25572
25725
|
});
|
|
25573
25726
|
const isPending = isCreatingFeatureAddon || isDeletingFeatureAddon;
|
|
@@ -25647,10 +25800,11 @@ const FeatureAddonRow_PriceListChargeFragment = t(`
|
|
|
25647
25800
|
}
|
|
25648
25801
|
`, [isAddonPurchased_PriceListChargeFragment, PricingTooltip_PriceListChargeFragment]);
|
|
25649
25802
|
function FeatureAddonRow({ featureAddon: maskedFeatureAddon, priceList: maskedPriceList, }) {
|
|
25803
|
+
const { quote: maskedQuote, selectedPriceList } = useContext(QuoteContext);
|
|
25650
25804
|
// Read fragments
|
|
25651
25805
|
const featureAddon = readFragment(FeatureAddonRow_PriceListChargeFragment, maskedFeatureAddon);
|
|
25652
25806
|
const priceList = readFragment(FeatureAddonRow_PriceListFragment, maskedPriceList);
|
|
25653
|
-
const
|
|
25807
|
+
const quote = readFragment(FeatureAddonRow_QuoteFragment, maskedQuote);
|
|
25654
25808
|
const { handleAddFeatureAddon, handleRemoveFeatureAddon, isPending, isChecked } = useQuoteUpdateFeatureAddon(quote, featureAddon);
|
|
25655
25809
|
const { brandColor } = useBrand();
|
|
25656
25810
|
const { upgradingSubscription } = useContext(SubscriptionsContext);
|
|
@@ -25865,107 +26019,84 @@ function AddonPlanModal({ onClose, priceList: maskedPriceList, }) {
|
|
|
25865
26019
|
return (jsx(StyledModal, { open: !!priceList, onCancel: onClose, footer: null, centered: true, children: jsxs("div", { className: `bunny-w-full bunny-overflow-hidden`, children: [jsx(GridTemplateColumnsWrapper, { className: "bunny-grid bunny-w-full", everythingInPlus: false, plansToDisplay: 1, children: priceList && (jsx(PriceListCard, { isSelected: true, priceList: priceList, noBorder: true, hideButton: true, disableCurrentPlan: true })) }), hasFeatureAddons && (jsxs(Fragment, { children: [jsx(Divider, { className: "bunny-my-0" }), jsx("div", { className: "bunny-flex bunny-flex-col bunny-gap-4 bunny-p-4", children: jsx(FeatureAddonsList, { priceList: priceList }) })] }))] }) }));
|
|
25866
26020
|
}
|
|
25867
26021
|
|
|
25868
|
-
const
|
|
25869
|
-
${
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
) {
|
|
25875
|
-
|
|
25876
|
-
|
|
25877
|
-
|
|
25878
|
-
|
|
25879
|
-
|
|
25880
|
-
|
|
25881
|
-
|
|
25882
|
-
id
|
|
25883
|
-
quote {
|
|
25884
|
-
...QuoteFields
|
|
26022
|
+
const mutation$3 = t(`
|
|
26023
|
+
mutation QuoteChangeCreate($quoteId: ID!, $priceListId: ID!, $parentQuoteChangeId: ID!) {
|
|
26024
|
+
quoteChangeCreate(
|
|
26025
|
+
quoteId: $quoteId
|
|
26026
|
+
priceListId: $priceListId
|
|
26027
|
+
parentQuoteChangeId: $parentQuoteChangeId
|
|
26028
|
+
) {
|
|
26029
|
+
errors
|
|
26030
|
+
quoteChange {
|
|
26031
|
+
id
|
|
26032
|
+
quote {
|
|
26033
|
+
...QuoteContext_QuoteFragment
|
|
26034
|
+
}
|
|
26035
|
+
}
|
|
25885
26036
|
}
|
|
25886
26037
|
}
|
|
25887
|
-
|
|
25888
|
-
}
|
|
25889
|
-
`;
|
|
26038
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25890
26039
|
const quoteChangeCreate = async ({ parentQuoteChangeId, priceListId, apiHost, token, quoteId, }) => {
|
|
25891
|
-
|
|
25892
|
-
const vars = {
|
|
25893
|
-
parentQuoteChangeId,
|
|
25894
|
-
priceListId,
|
|
25895
|
-
quoteId,
|
|
25896
|
-
};
|
|
25897
|
-
const response = await gqlRequest({
|
|
25898
|
-
query: QUOTE_CHANGE_CREATE,
|
|
25899
|
-
token,
|
|
25900
|
-
vars,
|
|
25901
|
-
apiHost,
|
|
25902
|
-
});
|
|
25903
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeCreate) === null || _a === void 0 ? void 0 : _a.errors;
|
|
25904
|
-
if (errors)
|
|
25905
|
-
throw errors;
|
|
26040
|
+
const response = await execute(mutation$3, { apiHost, token }, { parentQuoteChangeId, priceListId, quoteId });
|
|
25906
26041
|
return response.quoteChangeCreate;
|
|
25907
26042
|
};
|
|
25908
26043
|
|
|
25909
|
-
const
|
|
25910
|
-
${
|
|
25911
|
-
|
|
25912
|
-
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
26044
|
+
const mutation$2 = t(`
|
|
26045
|
+
mutation QuoteChangeDelete($id: ID!) {
|
|
26046
|
+
quoteChangeDelete(id: $id) {
|
|
26047
|
+
errors
|
|
26048
|
+
quoteChange {
|
|
26049
|
+
quote {
|
|
26050
|
+
...QuoteContext_QuoteFragment
|
|
26051
|
+
}
|
|
25917
26052
|
}
|
|
25918
26053
|
}
|
|
25919
26054
|
}
|
|
25920
|
-
|
|
25921
|
-
`;
|
|
26055
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25922
26056
|
const quoteChangeDelete = async ({ id, apiHost, token, }) => {
|
|
25923
|
-
|
|
25924
|
-
const vars = {
|
|
25925
|
-
id,
|
|
25926
|
-
};
|
|
25927
|
-
const response = await gqlRequest({
|
|
25928
|
-
query: QUOTE_CHANGE_DELETE,
|
|
25929
|
-
token,
|
|
25930
|
-
vars,
|
|
25931
|
-
apiHost,
|
|
25932
|
-
});
|
|
25933
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeDelete) === null || _a === void 0 ? void 0 : _a.errors;
|
|
25934
|
-
if (errors)
|
|
25935
|
-
throw errors;
|
|
26057
|
+
const response = await execute(mutation$2, { apiHost, token }, { id });
|
|
25936
26058
|
return response.quoteChangeDelete;
|
|
25937
26059
|
};
|
|
25938
26060
|
|
|
25939
|
-
const useToggleAddonPlan = (
|
|
26061
|
+
const useToggleAddonPlan = (maskedQuote, addonPriceListId, selectedPriceList, setIsAddonPlanLoading) => {
|
|
25940
26062
|
const token = useToken();
|
|
25941
26063
|
const isAdded = useRef(false);
|
|
25942
|
-
const queryClient = useQueryClient();
|
|
25943
26064
|
const { apiHost } = useContext(BunnyContext);
|
|
26065
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
26066
|
+
// Read fragments
|
|
26067
|
+
const quote = readFragment(useToggleAddonPlan_QuoteFragment, maskedQuote);
|
|
25944
26068
|
const parentQuoteChange = useMemo(() => {
|
|
25945
|
-
|
|
26069
|
+
var _a;
|
|
26070
|
+
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; });
|
|
25946
26071
|
}, [quote, selectedPriceList]);
|
|
25947
26072
|
const { mutate: addAddonQuoteChange, isPending: isAddingAddonQuoteChange } = useMutation({
|
|
25948
26073
|
mutationFn: quoteChangeCreate,
|
|
25949
|
-
onSuccess:
|
|
26074
|
+
onSuccess: quoteChangeCreate => {
|
|
26075
|
+
var _a;
|
|
25950
26076
|
isAdded.current = true;
|
|
25951
|
-
const updatedQuote = quoteChangeCreate.quoteChange.quote;
|
|
25952
|
-
|
|
25953
|
-
|
|
25954
|
-
|
|
25955
|
-
|
|
25956
|
-
|
|
26077
|
+
const updatedQuote = (_a = quoteChangeCreate === null || quoteChangeCreate === void 0 ? void 0 : quoteChangeCreate.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26078
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26079
|
+
throw new Error('Updated quote ID not found');
|
|
26080
|
+
}
|
|
26081
|
+
if (!updatedQuote) {
|
|
26082
|
+
throw new Error('Updated quote not found');
|
|
26083
|
+
}
|
|
26084
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25957
26085
|
},
|
|
25958
26086
|
});
|
|
25959
26087
|
const { mutate: deleteQuoteChange, isPending: isDeletingQuoteChange } = useMutation({
|
|
25960
26088
|
mutationFn: quoteChangeDelete,
|
|
25961
|
-
onSuccess:
|
|
26089
|
+
onSuccess: quoteChangeDelete => {
|
|
26090
|
+
var _a;
|
|
25962
26091
|
isAdded.current = false;
|
|
25963
|
-
const updatedQuote = quoteChangeDelete.quoteChange.quote;
|
|
25964
|
-
|
|
25965
|
-
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
26092
|
+
const updatedQuote = (_a = quoteChangeDelete === null || quoteChangeDelete === void 0 ? void 0 : quoteChangeDelete.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26093
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26094
|
+
throw new Error('Updated quote ID not found');
|
|
26095
|
+
}
|
|
26096
|
+
if (!updatedQuote) {
|
|
26097
|
+
throw new Error('Updated quote not found');
|
|
26098
|
+
}
|
|
26099
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25969
26100
|
},
|
|
25970
26101
|
});
|
|
25971
26102
|
function handleAddAddonQuoteChange() {
|
|
@@ -25975,6 +26106,9 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25975
26106
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25976
26107
|
throw new Error('Quote ID not found');
|
|
25977
26108
|
}
|
|
26109
|
+
if (!parentQuoteChange.id) {
|
|
26110
|
+
throw new Error('Parent quote change ID not found');
|
|
26111
|
+
}
|
|
25978
26112
|
addAddonQuoteChange({
|
|
25979
26113
|
parentQuoteChangeId: parentQuoteChange.id,
|
|
25980
26114
|
priceListId: addonPriceListId,
|
|
@@ -25984,9 +26118,10 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25984
26118
|
});
|
|
25985
26119
|
}
|
|
25986
26120
|
function handleDeleteQuoteChange() {
|
|
25987
|
-
|
|
25988
|
-
|
|
25989
|
-
|
|
26121
|
+
var _a;
|
|
26122
|
+
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; });
|
|
26123
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id)) {
|
|
26124
|
+
throw new Error('Quote change ID not found');
|
|
25990
26125
|
}
|
|
25991
26126
|
deleteQuoteChange({
|
|
25992
26127
|
id: quoteChange.id,
|
|
@@ -26020,6 +26155,7 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26020
26155
|
plan {
|
|
26021
26156
|
description
|
|
26022
26157
|
name
|
|
26158
|
+
pricingDescription
|
|
26023
26159
|
}
|
|
26024
26160
|
...PriceListCardPriceDescription_PriceListFragment
|
|
26025
26161
|
...PriceListCardPrice_PriceListFragment
|
|
@@ -26033,16 +26169,18 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26033
26169
|
PriceListCardPriceDescription_PriceListFragment,
|
|
26034
26170
|
]);
|
|
26035
26171
|
function AddonPlanRow({ addonPriceList: maskedAddonPriceList, selectedPriceList, onClickSelect, isPurchased, }) {
|
|
26036
|
-
var _a, _b, _c, _d, _e, _f;
|
|
26172
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
26037
26173
|
// Read fragments
|
|
26038
26174
|
const addonPriceList = readFragment(AddonPlanRow_PriceListFragment, maskedAddonPriceList);
|
|
26039
|
-
const { quote, setIsAddonPlanLoading } = useContext(QuoteContext);
|
|
26175
|
+
const { quote: maskedQuote, setIsAddonPlanLoading } = useContext(QuoteContext);
|
|
26176
|
+
const quote = readFragment(AddonPlanRow_QuoteFragment, maskedQuote);
|
|
26040
26177
|
const { shadow, isInPreviewMode } = useContext(SubscriptionsContext);
|
|
26041
26178
|
const { isPending, addedQuoteChange, addAddonQuoteChange, deleteQuoteChange } = useToggleAddonPlan(quote, addonPriceList.id, selectedPriceList, setIsAddonPlanLoading);
|
|
26042
26179
|
const activeCharge = (_a = getActivePlanPriceData(addonPriceList, selectedPriceList)) === null || _a === void 0 ? void 0 : _a.activeCharge;
|
|
26043
26180
|
// Derived state
|
|
26044
26181
|
const switchDisabled = isInPreviewMode || isPurchased;
|
|
26045
|
-
|
|
26182
|
+
const hasCustomPrice = ((_b = addonPriceList.plan) === null || _b === void 0 ? void 0 : _b.pricingDescription) != null;
|
|
26183
|
+
return (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: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [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 }), jsx(PriceListCardDescription, { description: (_e = (_d = addonPriceList.plan) === null || _d === void 0 ? void 0 : _d.description) !== null && _e !== void 0 ? _e : '' }), !hasCustomPrice && (jsx(PriceListCardPrice, { priceList: addonPriceList, className: "bunny-text-sm bunny-font-medium bunny-text-gray-900" })), jsx(PriceListCardPriceDescription, { feature: activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.feature, priceList: addonPriceList }), jsx(Button, { type: "link", onClick: onClickSelect, children: jsx(InfoCircleOutlined, {}) })] }), jsx(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) => {
|
|
26046
26184
|
if (checked) {
|
|
26047
26185
|
addAddonQuoteChange();
|
|
26048
26186
|
}
|
|
@@ -26066,7 +26204,7 @@ const AddonPlans_PlanFragment = t(`
|
|
|
26066
26204
|
}
|
|
26067
26205
|
`, [AddonPlanModal_PriceListFragment, AddonPlanRow_PriceListFragment]);
|
|
26068
26206
|
|
|
26069
|
-
const query = t(`
|
|
26207
|
+
const query$2 = t(`
|
|
26070
26208
|
query PriceList($id: ID!) {
|
|
26071
26209
|
priceList(id: $id) {
|
|
26072
26210
|
addonPlans {
|
|
@@ -26080,7 +26218,7 @@ const query = t(`
|
|
|
26080
26218
|
`, [AddonPlans_PlanFragment]);
|
|
26081
26219
|
const getAddonPlans = async ({ token, id, apiHost, }) => {
|
|
26082
26220
|
var _a;
|
|
26083
|
-
const response = await execute(query, { apiHost, token }, { id });
|
|
26221
|
+
const response = await execute(query$2, { apiHost, token }, { id });
|
|
26084
26222
|
const addonPlans = (_a = response === null || response === void 0 ? void 0 : response.priceList) === null || _a === void 0 ? void 0 : _a.addonPlans;
|
|
26085
26223
|
// for each addon plan, filter out the price lists that are not visible
|
|
26086
26224
|
const visibleAddonPlans = addonPlans === null || addonPlans === void 0 ? void 0 : addonPlans.map(addonPlan => {
|
|
@@ -26188,7 +26326,10 @@ const PriceListGrid = ({ availablePriceLists, priceListChangeOptions, priceListS
|
|
|
26188
26326
|
onClickPriceListCard: onClickPriceListCard })) : (jsx(PriceListGridDesktop, { availablePriceLists: availablePriceLists, priceListChangeOptions: priceListChangeOptions, priceListStart: priceListStart, selectedPriceList: selectedPriceList, selectedProduct: selectedProduct, setPriceListStart: setPriceListStart, subscriptions: subscriptions, trialRemainingDays: trialRemainingDays, selectedBillingPeriod: selectedBillingPeriod, onClickPriceListCard: onClickPriceListCard }));
|
|
26189
26327
|
};
|
|
26190
26328
|
|
|
26191
|
-
const createAvailableBillingPeriods = (priceLists, selectedProduct) => {
|
|
26329
|
+
const createAvailableBillingPeriods = (priceLists, selectedProduct, upgradingSubscription) => {
|
|
26330
|
+
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true) {
|
|
26331
|
+
return [upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.periodMonths];
|
|
26332
|
+
}
|
|
26192
26333
|
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));
|
|
26193
26334
|
};
|
|
26194
26335
|
const showInfoNotification$1 = useInfoNotification();
|
|
@@ -26202,11 +26343,18 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26202
26343
|
const [selectedBillingPeriod, setSelectedBillingPeriod] = useState(null);
|
|
26203
26344
|
const [priceListStart, setPriceListStart] = useState(0);
|
|
26204
26345
|
// Derived state
|
|
26205
|
-
const availableBillingPeriods = useMemo(() => createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct), [priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct]);
|
|
26346
|
+
const availableBillingPeriods = useMemo(() => createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct, upgradingSubscription), [priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct]);
|
|
26347
|
+
// TODO: clean up available pricelists calculation. We should calculate it once, not three times.
|
|
26348
|
+
const subscriptionIsAddon = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true;
|
|
26206
26349
|
const availablePriceLists = useMemo(() => {
|
|
26207
26350
|
var _a;
|
|
26208
|
-
|
|
26209
|
-
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id))
|
|
26351
|
+
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 &&
|
|
26352
|
+
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id));
|
|
26353
|
+
// If the subscription is an addon, we should only show its price lists because we don't support changing add-on plans.
|
|
26354
|
+
if (subscriptionIsAddon) {
|
|
26355
|
+
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))) || []);
|
|
26356
|
+
}
|
|
26357
|
+
return priceLists.filter(priceList => priceList.plan.addon !== true) || [];
|
|
26210
26358
|
}, [priceListChangeOptions, selectedBillingPeriod, selectedProduct]);
|
|
26211
26359
|
// Handlers
|
|
26212
26360
|
const onChangeBillingPeriod = useCallback((billingPeriod) => {
|
|
@@ -26235,7 +26383,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26235
26383
|
}
|
|
26236
26384
|
}, [selectedPriceList, priceListChangeOptions, upgradingSubscription]);
|
|
26237
26385
|
const onChangeProduct = useCallback((product) => {
|
|
26238
|
-
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product);
|
|
26386
|
+
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product, upgradingSubscription);
|
|
26239
26387
|
if (selectedBillingPeriod &&
|
|
26240
26388
|
!(newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods.includes(billingPeriodConverter(selectedBillingPeriod)))) {
|
|
26241
26389
|
onChangeBillingPeriod(periodMonthsConverter((newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods[0]) !== undefined ? newAvailableBillingPeriods[0] : 1));
|
|
@@ -26246,7 +26394,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26246
26394
|
const initialProduct = (_a = priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.products) === null || _a === void 0 ? void 0 : _a[0];
|
|
26247
26395
|
const initialBillingPeriod = useMemo(() => {
|
|
26248
26396
|
var _a, _b, _c;
|
|
26249
|
-
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct);
|
|
26397
|
+
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct, upgradingSubscription);
|
|
26250
26398
|
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);
|
|
26251
26399
|
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) &&
|
|
26252
26400
|
periodMonthsConverted &&
|
|
@@ -26902,80 +27050,177 @@ const PageSubTitle = ({ title }) => {
|
|
|
26902
27050
|
return (jsx("div", { className: "bunny-shrink-0", style: { color: secondaryColor }, children: title }));
|
|
26903
27051
|
};
|
|
26904
27052
|
|
|
26905
|
-
const
|
|
26906
|
-
|
|
26907
|
-
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
27053
|
+
const AccountContactsFragment = t(`
|
|
27054
|
+
fragment AccountContactsFragment on Contact {
|
|
27055
|
+
id
|
|
27056
|
+
email
|
|
27057
|
+
firstName
|
|
27058
|
+
}
|
|
27059
|
+
`, []);
|
|
27060
|
+
|
|
27061
|
+
const AddContactButton = ({ onClick }) => {
|
|
27062
|
+
return (jsx("div", { className: "bunny-border-t bunny-border-gray-200 bunny-p-2", children: jsx(Button, { type: "text", className: "bunny-w-full bunny-text-left", onClick: onClick, children: "+ Add new contact" }) }));
|
|
27063
|
+
};
|
|
27064
|
+
|
|
27065
|
+
const useSetAccountContactsQueryData = () => {
|
|
27066
|
+
const token = useToken();
|
|
27067
|
+
const queryClient = useQueryClient();
|
|
27068
|
+
const setAccountContactsQueryData = (accountId, updater) => {
|
|
27069
|
+
queryClient.setQueryData(QueryKeyFactory.accountContactsKey({ accountId, token }), updater);
|
|
27070
|
+
};
|
|
27071
|
+
return { setAccountContactsQueryData };
|
|
27072
|
+
};
|
|
27073
|
+
|
|
27074
|
+
const mutation$1 = t(`
|
|
27075
|
+
mutation ContactCreate($attributes: ContactAttributes!) {
|
|
27076
|
+
contactCreate(attributes: $attributes) {
|
|
27077
|
+
contact {
|
|
27078
|
+
id
|
|
27079
|
+
account {
|
|
27080
|
+
contacts {
|
|
27081
|
+
...AccountContactsFragment
|
|
27082
|
+
}
|
|
26915
27083
|
}
|
|
26916
|
-
billingCountry
|
|
26917
|
-
billingState
|
|
26918
|
-
billingStreet
|
|
26919
|
-
billingZip
|
|
26920
|
-
name
|
|
26921
|
-
taxNumber
|
|
26922
27084
|
}
|
|
26923
27085
|
errors
|
|
26924
27086
|
}
|
|
26925
|
-
|
|
26926
|
-
|
|
26927
|
-
const
|
|
26928
|
-
var _a;
|
|
26929
|
-
const
|
|
26930
|
-
|
|
26931
|
-
|
|
26932
|
-
|
|
26933
|
-
|
|
26934
|
-
|
|
27087
|
+
}
|
|
27088
|
+
`, [AccountContactsFragment]);
|
|
27089
|
+
const contactCreate = async ({ attributes, apiHost, token }) => {
|
|
27090
|
+
var _a, _b;
|
|
27091
|
+
const response = await execute(mutation$1, { apiHost, token }, { attributes });
|
|
27092
|
+
if ((_a = response.contactCreate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
27093
|
+
throw new Error(response.contactCreate.errors[0]);
|
|
27094
|
+
}
|
|
27095
|
+
return (_b = response.contactCreate) === null || _b === void 0 ? void 0 : _b.contact;
|
|
27096
|
+
};
|
|
27097
|
+
|
|
27098
|
+
const AddContactModal = ({ open, onClose, accountId, onContactCreated, }) => {
|
|
27099
|
+
const [form] = Form.useForm();
|
|
27100
|
+
const { apiHost } = useContext(BunnyContext);
|
|
27101
|
+
const token = useToken();
|
|
27102
|
+
const showErrorNotification = useErrorNotification();
|
|
27103
|
+
const showSuccessNotification = useSuccessNotification();
|
|
27104
|
+
const { setAccountContactsQueryData } = useSetAccountContactsQueryData();
|
|
27105
|
+
const { mutate: createContact, isPending: isCreatingContact } = useMutation({
|
|
27106
|
+
mutationFn: (attributes) => contactCreate({ attributes, apiHost, token }),
|
|
27107
|
+
onSuccess: newContact => {
|
|
27108
|
+
var _a, _b;
|
|
27109
|
+
showSuccessNotification('Contact created successfully');
|
|
27110
|
+
// Add the new contact to the cache
|
|
27111
|
+
if (newContact && accountId) {
|
|
27112
|
+
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);
|
|
27113
|
+
}
|
|
27114
|
+
onClose();
|
|
27115
|
+
form.resetFields();
|
|
27116
|
+
const newContactData = newContact ? readFragment(AccountContactsFragment, newContact) : null;
|
|
27117
|
+
if (newContactData === null || newContactData === void 0 ? void 0 : newContactData.id) {
|
|
27118
|
+
onContactCreated === null || onContactCreated === void 0 ? void 0 : onContactCreated(newContactData.id);
|
|
27119
|
+
}
|
|
27120
|
+
},
|
|
26935
27121
|
});
|
|
26936
|
-
const
|
|
26937
|
-
|
|
26938
|
-
|
|
26939
|
-
|
|
27122
|
+
const handleAddContact = () => {
|
|
27123
|
+
if (!accountId) {
|
|
27124
|
+
showErrorNotification('Account ID is required to create a contact');
|
|
27125
|
+
return;
|
|
27126
|
+
}
|
|
27127
|
+
form.validateFields().then(values => {
|
|
27128
|
+
createContact({
|
|
27129
|
+
email: values.email || null,
|
|
27130
|
+
firstName: values.firstName || null,
|
|
27131
|
+
lastName: values.lastName || null,
|
|
27132
|
+
accountId: accountId,
|
|
27133
|
+
portalAccess: true,
|
|
27134
|
+
});
|
|
27135
|
+
});
|
|
27136
|
+
};
|
|
27137
|
+
return (jsx(Modal, { title: "Add new contact", open: open, onCancel: () => {
|
|
27138
|
+
onClose();
|
|
27139
|
+
form.resetFields();
|
|
27140
|
+
}, footer: [
|
|
27141
|
+
jsx(Button, { onClick: () => {
|
|
27142
|
+
onClose();
|
|
27143
|
+
form.resetFields();
|
|
27144
|
+
}, children: "Cancel" }, "cancel"),
|
|
27145
|
+
jsx(Button, { type: "primary", loading: isCreatingContact, onClick: handleAddContact, children: "Add contact" }, "submit"),
|
|
27146
|
+
], children: jsxs(Form, { form: form, layout: "vertical", className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsx(Form.Item, { label: "First name", name: "firstName", rules: [{ required: false }], children: jsx(Input, { placeholder: "Enter first name" }) }), jsx(Form.Item, { label: "Last name", name: "lastName", rules: [{ required: false }], children: jsx(Input, { placeholder: "Enter last name" }) }), jsx(Form.Item, { label: "Email", name: "email", rules: [
|
|
27147
|
+
{ required: true, message: 'Email is required' },
|
|
27148
|
+
{ type: 'email', message: 'Please enter a valid email' },
|
|
27149
|
+
], children: jsx(Input, { placeholder: "Enter email" }) })] }) }));
|
|
26940
27150
|
};
|
|
26941
27151
|
|
|
26942
|
-
const
|
|
26943
|
-
|
|
26944
|
-
billingDetails {
|
|
26945
|
-
billingCity
|
|
26946
|
-
billingContact {
|
|
26947
|
-
email
|
|
26948
|
-
}
|
|
26949
|
-
billingCountry
|
|
26950
|
-
billingState
|
|
26951
|
-
billingStreet
|
|
26952
|
-
billingZip
|
|
26953
|
-
name
|
|
26954
|
-
taxNumber
|
|
26955
|
-
currency {
|
|
27152
|
+
const BillingDetailsSection_AccountFragment = t(`
|
|
27153
|
+
fragment BillingDetailsSection_AccountFragment on Account {
|
|
26956
27154
|
id
|
|
27155
|
+
name
|
|
27156
|
+
billingStreet
|
|
27157
|
+
billingCity
|
|
27158
|
+
billingState
|
|
27159
|
+
billingZip
|
|
27160
|
+
billingCountry
|
|
27161
|
+
taxNumber
|
|
27162
|
+
billingContactId
|
|
27163
|
+
secondaryBillingContactIds
|
|
27164
|
+
billingContact {
|
|
27165
|
+
email
|
|
27166
|
+
firstName
|
|
27167
|
+
}
|
|
26957
27168
|
}
|
|
26958
|
-
|
|
26959
|
-
|
|
26960
|
-
const
|
|
27169
|
+
`, []);
|
|
27170
|
+
|
|
27171
|
+
const mutation = t(`
|
|
27172
|
+
mutation AccountUpdate($id: ID!, $attributes: AccountAttributes!) {
|
|
27173
|
+
accountUpdate(id: $id, attributes: $attributes) {
|
|
27174
|
+
account {
|
|
27175
|
+
...BillingDetailsSection_AccountFragment
|
|
27176
|
+
}
|
|
27177
|
+
errors
|
|
27178
|
+
}
|
|
27179
|
+
}
|
|
27180
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27181
|
+
const accountUpdate = async ({ accountId, attributes, apiHost, token, }) => {
|
|
26961
27182
|
var _a;
|
|
26962
|
-
const response = await
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
27183
|
+
const response = await execute(mutation, { apiHost, token }, { id: accountId, attributes });
|
|
27184
|
+
return (_a = response.accountUpdate) === null || _a === void 0 ? void 0 : _a.account;
|
|
27185
|
+
};
|
|
27186
|
+
|
|
27187
|
+
const query$1 = t(`
|
|
27188
|
+
query GetAccount($id: ID!) {
|
|
27189
|
+
account(id: $id) {
|
|
27190
|
+
...BillingDetailsSection_AccountFragment
|
|
27191
|
+
}
|
|
27192
|
+
}
|
|
27193
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27194
|
+
const getAccount = async ({ accountId, apiHost, token, }) => {
|
|
27195
|
+
const response = await execute(query$1, { apiHost, token }, { id: accountId });
|
|
27196
|
+
return response.account;
|
|
27197
|
+
};
|
|
27198
|
+
|
|
27199
|
+
const query = t(`
|
|
27200
|
+
query GetAccountContacts($accountId: ID!) {
|
|
27201
|
+
account(id: $accountId) {
|
|
27202
|
+
id
|
|
27203
|
+
contacts {
|
|
27204
|
+
...AccountContactsFragment
|
|
27205
|
+
}
|
|
27206
|
+
}
|
|
26969
27207
|
}
|
|
26970
|
-
|
|
27208
|
+
`, [AccountContactsFragment]);
|
|
27209
|
+
const getAccountContacts = async ({ accountId, apiHost, token, }) => {
|
|
27210
|
+
var _a;
|
|
27211
|
+
const response = await execute(query, { apiHost, token }, { accountId });
|
|
27212
|
+
return (_a = response.account) === null || _a === void 0 ? void 0 : _a.contacts;
|
|
26971
27213
|
};
|
|
26972
27214
|
|
|
26973
27215
|
const { Text } = Typography;
|
|
26974
27216
|
function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
27217
|
+
var _a, _b, _c;
|
|
26975
27218
|
// State
|
|
26976
27219
|
const [isFormEdited, setIsFormEdited] = useState(false);
|
|
26977
27220
|
const [form] = Form.useForm();
|
|
26978
27221
|
const values = Form.useWatch([], form);
|
|
27222
|
+
const [isAddContactModalOpen, setIsAddContactModalOpen] = useState(false);
|
|
27223
|
+
const [contactFieldType, setContactFieldType] = useState(null);
|
|
26979
27224
|
// Context
|
|
26980
27225
|
const { apiHost } = useContext(BunnyContext);
|
|
26981
27226
|
const token = useToken();
|
|
@@ -26984,14 +27229,37 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
26984
27229
|
const queryClient = useQueryClient();
|
|
26985
27230
|
const showErrorNotification = useErrorNotification();
|
|
26986
27231
|
const showSuccessNotification = useSuccessNotification();
|
|
27232
|
+
const { currentUser } = useCurrentUserData(token);
|
|
27233
|
+
const accountId = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.account) === null || _a === void 0 ? void 0 : _a.id;
|
|
26987
27234
|
// Queries
|
|
26988
|
-
const { data:
|
|
26989
|
-
queryKey: QueryKeyFactory
|
|
26990
|
-
queryFn: () =>
|
|
27235
|
+
const { data: maskedAccount, isLoading: isLoadingAccount } = useQuery({
|
|
27236
|
+
queryKey: QueryKeyFactory.accountBillingDetailsKey({ accountId, token }),
|
|
27237
|
+
queryFn: () => {
|
|
27238
|
+
if (!accountId) {
|
|
27239
|
+
throw new Error('Account ID is required');
|
|
27240
|
+
}
|
|
27241
|
+
return getAccount({ accountId, apiHost, token });
|
|
27242
|
+
},
|
|
27243
|
+
enabled: !!accountId,
|
|
27244
|
+
});
|
|
27245
|
+
const account = readFragment(BillingDetailsSection_AccountFragment, maskedAccount);
|
|
27246
|
+
const { data: contacts, isLoading: isLoadingContacts } = useQuery({
|
|
27247
|
+
queryKey: QueryKeyFactory.accountContactsKey({ accountId, token }),
|
|
27248
|
+
queryFn: () => {
|
|
27249
|
+
if (!accountId) {
|
|
27250
|
+
throw new Error('Account ID is required');
|
|
27251
|
+
}
|
|
27252
|
+
return getAccountContacts({ accountId, apiHost, token });
|
|
27253
|
+
},
|
|
27254
|
+
enabled: !!accountId,
|
|
26991
27255
|
});
|
|
26992
|
-
const { mutate:
|
|
27256
|
+
const { mutate: updateAccount, isPending: isUpdatingAccount } = useMutation({
|
|
26993
27257
|
mutationFn: async (changedFormData) => {
|
|
26994
|
-
|
|
27258
|
+
if (!accountId) {
|
|
27259
|
+
throw new Error('Account ID is required');
|
|
27260
|
+
}
|
|
27261
|
+
const updatedAccount = await accountUpdate({
|
|
27262
|
+
accountId,
|
|
26995
27263
|
attributes: {
|
|
26996
27264
|
name: changedFormData.name,
|
|
26997
27265
|
billingStreet: changedFormData.billingStreet,
|
|
@@ -26999,77 +27267,92 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
26999
27267
|
billingZip: changedFormData.billingZip,
|
|
27000
27268
|
billingState: changedFormData.billingState,
|
|
27001
27269
|
billingCountry: changedFormData.billingCountry,
|
|
27002
|
-
billingContactEmail: changedFormData.billingContactEmail,
|
|
27003
27270
|
taxNumber: changedFormData.taxNumber,
|
|
27271
|
+
billingContactId: changedFormData.billingContactId || null,
|
|
27272
|
+
secondaryBillingContactIds: Array.isArray(changedFormData.secondaryBillingContactIds)
|
|
27273
|
+
? changedFormData.secondaryBillingContactIds
|
|
27274
|
+
: null,
|
|
27004
27275
|
},
|
|
27005
27276
|
token,
|
|
27006
27277
|
apiHost,
|
|
27007
27278
|
});
|
|
27008
|
-
queryClient.setQueryData(QueryKeyFactory
|
|
27009
|
-
|
|
27010
|
-
...old,
|
|
27011
|
-
...updatedBillingDetails.billingDetails,
|
|
27012
|
-
};
|
|
27013
|
-
});
|
|
27014
|
-
return updatedBillingDetails;
|
|
27279
|
+
queryClient.setQueryData(QueryKeyFactory.accountBillingDetailsKey({ accountId, token }), updatedAccount);
|
|
27280
|
+
return updatedAccount;
|
|
27015
27281
|
},
|
|
27016
27282
|
onSuccess: () => {
|
|
27017
27283
|
showSuccessNotification('Your account details have been saved');
|
|
27018
27284
|
queryClient.invalidateQueries({
|
|
27019
|
-
queryKey: QueryKeyFactory
|
|
27285
|
+
queryKey: QueryKeyFactory.taxationRequiredAccountFieldsKey({
|
|
27020
27286
|
token,
|
|
27021
27287
|
}),
|
|
27022
27288
|
});
|
|
27023
27289
|
},
|
|
27024
27290
|
});
|
|
27025
|
-
// Set form values when
|
|
27291
|
+
// Set form values when account is loaded
|
|
27026
27292
|
useEffect(() => {
|
|
27027
|
-
|
|
27028
|
-
if (billingDetails) {
|
|
27293
|
+
if (account) {
|
|
27029
27294
|
form.setFieldsValue({
|
|
27030
|
-
billingStreet:
|
|
27031
|
-
billingCity:
|
|
27032
|
-
billingZip:
|
|
27033
|
-
billingState:
|
|
27034
|
-
billingCountry:
|
|
27035
|
-
|
|
27036
|
-
|
|
27295
|
+
billingStreet: account.billingStreet,
|
|
27296
|
+
billingCity: account.billingCity,
|
|
27297
|
+
billingZip: account.billingZip,
|
|
27298
|
+
billingState: account.billingState,
|
|
27299
|
+
billingCountry: account.billingCountry,
|
|
27300
|
+
billingContactId: account.billingContactId,
|
|
27301
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27302
|
+
taxNumber: account.taxNumber,
|
|
27037
27303
|
});
|
|
27038
27304
|
}
|
|
27039
|
-
}, [
|
|
27305
|
+
}, [account]);
|
|
27040
27306
|
useEffect(() => {
|
|
27041
27307
|
form.validateFields({ validateOnly: true });
|
|
27042
27308
|
const isFormEdited = () => {
|
|
27043
|
-
|
|
27044
|
-
if (!billingDetails)
|
|
27309
|
+
if (!account)
|
|
27045
27310
|
return false;
|
|
27046
27311
|
const currentValues = form.getFieldsValue();
|
|
27047
27312
|
const accountValues = {
|
|
27048
|
-
billingStreet:
|
|
27049
|
-
billingCity:
|
|
27050
|
-
billingZip:
|
|
27051
|
-
billingState:
|
|
27052
|
-
billingCountry:
|
|
27053
|
-
|
|
27054
|
-
|
|
27313
|
+
billingStreet: account.billingStreet,
|
|
27314
|
+
billingCity: account.billingCity,
|
|
27315
|
+
billingZip: account.billingZip,
|
|
27316
|
+
billingState: account.billingState,
|
|
27317
|
+
billingCountry: account.billingCountry,
|
|
27318
|
+
billingContactId: account.billingContactId,
|
|
27319
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27320
|
+
taxNumber: account.taxNumber,
|
|
27055
27321
|
};
|
|
27056
|
-
return Object.keys(
|
|
27322
|
+
return Object.keys(accountValues).some(key => {
|
|
27057
27323
|
const value = accountValues[key];
|
|
27058
|
-
|
|
27324
|
+
const currentValue = currentValues[key];
|
|
27325
|
+
// Handle array comparison for secondaryBillingContactIds
|
|
27326
|
+
if (Array.isArray(value) && Array.isArray(currentValue)) {
|
|
27327
|
+
return JSON.stringify(value === null || value === void 0 ? void 0 : value.sort()) !== JSON.stringify(currentValue === null || currentValue === void 0 ? void 0 : currentValue.sort());
|
|
27328
|
+
}
|
|
27329
|
+
return currentValue !== value;
|
|
27059
27330
|
});
|
|
27060
27331
|
};
|
|
27061
27332
|
setIsFormEdited(isFormEdited());
|
|
27062
|
-
}, [form, values,
|
|
27333
|
+
}, [form, values, account]);
|
|
27063
27334
|
// Validate form fields when isFormEdited changes
|
|
27064
27335
|
useEffect(() => {
|
|
27065
27336
|
const validateOnly = isFormEdited ? false : true;
|
|
27066
27337
|
form.validateFields({ validateOnly: validateOnly });
|
|
27067
27338
|
}, [isFormEdited]);
|
|
27339
|
+
const handleContactCreated = (contactId) => {
|
|
27340
|
+
if (contactFieldType === 'primary') {
|
|
27341
|
+
form.setFieldValue('billingContactId', contactId);
|
|
27342
|
+
}
|
|
27343
|
+
else if (contactFieldType === 'secondary') {
|
|
27344
|
+
const currentSecondaryContacts = form.getFieldValue('secondaryBillingContactIds') || [];
|
|
27345
|
+
if (!currentSecondaryContacts.includes(contactId)) {
|
|
27346
|
+
form.setFieldValue('secondaryBillingContactIds', [...currentSecondaryContacts, contactId]);
|
|
27347
|
+
}
|
|
27348
|
+
}
|
|
27349
|
+
setContactFieldType(null);
|
|
27350
|
+
};
|
|
27068
27351
|
const saveBillingDetails = async () => {
|
|
27069
27352
|
form.validateFields({ validateOnly: false }).then(async () => {
|
|
27070
27353
|
try {
|
|
27071
27354
|
await form.validateFields();
|
|
27072
|
-
|
|
27355
|
+
updateAccount(form.getFieldsValue());
|
|
27073
27356
|
}
|
|
27074
27357
|
catch (error) {
|
|
27075
27358
|
if (error instanceof Error) {
|
|
@@ -27087,21 +27370,38 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
27087
27370
|
const filteredCountryList = useMemo(() => {
|
|
27088
27371
|
return countryListFilter ? Lists.COUNTRY_LIST.filter(countryListFilter) : Lists.COUNTRY_LIST;
|
|
27089
27372
|
}, [countryListFilter]);
|
|
27090
|
-
|
|
27091
|
-
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
((
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27104
|
-
|
|
27373
|
+
const isLoading = isLoadingAccount || isLoadingContacts;
|
|
27374
|
+
return (jsxs("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: [jsxs("div", { className: "bunny-px-4", children: [jsxs(Skeleton, { loading: isLoading || account === undefined, children: [jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (account === null || account === void 0 ? void 0 : account.name) || 'No company name' }) }), jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingAccount, autoComplete: "off", requiredMark: false, children: [jsx(Form.Item, { label: "Street address", name: "billingStreet", rules: [{ required: true, message: 'Street address is required' }], children: jsx(Input, {}) }), jsxs("div", { className: "bunny-flex bunny-gap-4", children: [jsx(Form.Item, { label: "City", name: "billingCity", rules: [{ required: true, message: 'City is required' }], className: "bunny-flex-1", children: jsx(Input, {}) }), jsx(Form.Item, { label: "Zipcode", name: "billingZip", rules: [{ required: true, message: 'Zipcode is required' }], className: "bunny-flex-1", children: jsx(Input, {}) })] }), jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-row bunny-pb-2' : 'bunny-flex-row'} bunny-gap-4`, children: [jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsx(Form.Item, { label: "State", name: "billingState", rules: [
|
|
27375
|
+
{
|
|
27376
|
+
required: false,
|
|
27377
|
+
},
|
|
27378
|
+
], children: jsx(Input, {}) }) }), jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsx(Form.Item, { label: "Country", name: "billingCountry", rules: [{ required: true, message: 'Country is required' }], children: jsx(Select, { className: "bunny-w-full", options: filteredCountryList, placeholder: "Select a country", popupMatchSelectWidth: false, showSearch: true, filterOption: (input, option) => {
|
|
27379
|
+
var _a, _b;
|
|
27380
|
+
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
27381
|
+
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
27382
|
+
} }) }) })] }), jsx(Form.Item, { label: "Primary billing contact", name: "billingContactId", rules: [{ required: true, message: 'Primary billing contact is required' }], children: jsx(Select, { className: "bunny-w-full", placeholder: "Select a contact", options: (_b = contacts === null || contacts === void 0 ? void 0 : contacts.map(contact => {
|
|
27383
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27384
|
+
return {
|
|
27385
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27386
|
+
? `${contactData.firstName}`
|
|
27387
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27388
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27389
|
+
};
|
|
27390
|
+
})) !== null && _b !== void 0 ? _b : [], popupRender: menu => (jsxs(Fragment, { children: [menu, jsx(AddContactButton, { onClick: () => setIsAddContactModalOpen(true) })] })) }) }), jsx(Form.Item, { label: "Secondary billing contacts", name: "secondaryBillingContactIds", children: jsx(Select, { className: "bunny-w-full", mode: "multiple", maxTagCount: "responsive", placeholder: "Select contacts", options: (_c = contacts === null || contacts === void 0 ? void 0 : contacts.map(contact => {
|
|
27391
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27392
|
+
return {
|
|
27393
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27394
|
+
? `${contactData.firstName}`
|
|
27395
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27396
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27397
|
+
};
|
|
27398
|
+
})) !== null && _c !== void 0 ? _c : [], popupRender: menu => (jsxs(Fragment, { children: [menu, jsx(AddContactButton, { onClick: () => {
|
|
27399
|
+
setContactFieldType('secondary');
|
|
27400
|
+
setIsAddContactModalOpen(true);
|
|
27401
|
+
} })] })) }) }), jsx(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: jsx(Input, {}) })] })] }), jsx(Button, { disabled: !isFormEdited || isUpdatingAccount || isLoading, className: "bunny-w-full bunny-mt-4", type: "primary", onClick: saveBillingDetails, children: "Save" })] }), jsx(AddContactModal, { open: isAddContactModalOpen, onClose: () => {
|
|
27402
|
+
setIsAddContactModalOpen(false);
|
|
27403
|
+
setContactFieldType(null);
|
|
27404
|
+
}, accountId: accountId, onContactCreated: handleContactCreated })] }));
|
|
27105
27405
|
}
|
|
27106
27406
|
|
|
27107
27407
|
const BillingDetails = ({ className, countryListFilter, hideBillingDetailsForm = false, hidePaymentMethodForm = false, isCardEnabled = true, isUpgradeFromTrial = false, shadow = 'shadow-md', onSavePaymentMethod, }) => {
|