@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.
Files changed (99) hide show
  1. package/dist/cjs/index.js +1204 -904
  2. package/dist/cjs/types/src/components/BillingDetails/BillingDetailsForm.d.ts +0 -1
  3. package/dist/cjs/types/src/components/BillingDetails/components/AddContactButton.d.ts +3 -0
  4. package/dist/cjs/types/src/components/BillingDetails/components/AddContactModal.d.ts +8 -0
  5. package/dist/cjs/types/src/components/BillingDetails/fragments/AccountContactsFragment.d.ts +9 -0
  6. package/dist/cjs/types/src/components/BillingDetails/fragments/BillingDetailsSection_AccountFragment.d.ts +20 -0
  7. package/dist/cjs/types/src/components/BillingDetails/hooks/useSetAccountContactsQueryData.d.ts +5 -0
  8. package/dist/cjs/types/src/components/BillingDetails/mutations/accountUpdate.d.ts +22 -0
  9. package/dist/cjs/types/src/components/BillingDetails/mutations/contactCreate.d.ts +22 -0
  10. package/dist/cjs/types/src/components/BillingDetails/queries/getAccount.d.ts +9 -0
  11. package/dist/cjs/types/src/components/BillingDetails/queries/getAccountContacts.d.ts +9 -0
  12. package/dist/cjs/types/src/components/Checkout/Checkout.d.ts +2 -1
  13. package/dist/cjs/types/src/components/QuoteProvider/context/QuoteContext.d.ts +1 -0
  14. package/dist/cjs/types/src/components/QuoteProvider/fragments/quoteFragment.d.ts +7 -0
  15. package/dist/cjs/types/src/components/QuoteProvider/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
  16. package/dist/cjs/types/src/components/QuoteProvider/hooks/useSetQuoteQueryData.d.ts +5 -0
  17. package/dist/cjs/types/src/components/QuoteProvider/mutations/quoteRecalculateTaxes.d.ts +11 -0
  18. package/dist/cjs/types/src/components/Subscriptions/AddonSubscriptionCards.d.ts +3 -2
  19. package/dist/cjs/types/src/components/Subscriptions/SubscriptionsListContainer.d.ts +2 -2
  20. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutBarSummarySection.d.ts +15 -2
  21. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutButton.d.ts +2 -2
  22. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +12 -3
  23. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/FeatureAddonRow_QuoteFragment.d.ts +9 -0
  24. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/useQuoteUpdateFeatureAddon_QuoteFragment.d.ts +8 -0
  25. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/hooks/useQuoteUpdateFeatureAddon.d.ts +9 -0
  26. package/dist/cjs/types/src/{graphql → components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons}/mutations/quoteChargeCreate.d.ts +12 -2
  27. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/components/AddonPlanRow.d.ts +1 -0
  28. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/AddonPlanRow_QuoteFragment.d.ts +9 -0
  29. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/useToggleAddonPlan_QuoteFragment.d.ts +13 -0
  30. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/hooks/useToggleAddonQuoteChange.d.ts +9 -0
  31. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeCreate.d.ts +18 -0
  32. package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeDelete.d.ts +15 -0
  33. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteIsLoadingContext.d.ts +5 -0
  34. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteRecalculateTaxesContext.d.ts +6 -0
  35. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
  36. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteDelete.d.ts +12 -0
  37. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteRecalculateTaxes.d.ts +11 -0
  38. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuantityInput.d.ts +10 -1
  39. package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuoteIsLoadingUpdater.d.ts +9 -0
  40. package/dist/cjs/types/src/components/Subscriptions/subscriptionsList/SubscriptionsList.d.ts +2 -2
  41. package/dist/cjs/types/src/components/Subscriptions/tieredDisplayDropdown/TieredDisplayDropdown.d.ts +3 -1
  42. package/dist/cjs/types/src/utils/QueryKeyFactory.d.ts +10 -0
  43. package/dist/esm/index.js +1206 -906
  44. package/dist/esm/types/src/components/BillingDetails/BillingDetailsForm.d.ts +0 -1
  45. package/dist/esm/types/src/components/BillingDetails/components/AddContactButton.d.ts +3 -0
  46. package/dist/esm/types/src/components/BillingDetails/components/AddContactModal.d.ts +8 -0
  47. package/dist/esm/types/src/components/BillingDetails/fragments/AccountContactsFragment.d.ts +9 -0
  48. package/dist/esm/types/src/components/BillingDetails/fragments/BillingDetailsSection_AccountFragment.d.ts +20 -0
  49. package/dist/esm/types/src/components/BillingDetails/hooks/useSetAccountContactsQueryData.d.ts +5 -0
  50. package/dist/esm/types/src/components/BillingDetails/mutations/accountUpdate.d.ts +22 -0
  51. package/dist/esm/types/src/components/BillingDetails/mutations/contactCreate.d.ts +22 -0
  52. package/dist/esm/types/src/components/BillingDetails/queries/getAccount.d.ts +9 -0
  53. package/dist/esm/types/src/components/BillingDetails/queries/getAccountContacts.d.ts +9 -0
  54. package/dist/esm/types/src/components/Checkout/Checkout.d.ts +2 -1
  55. package/dist/esm/types/src/components/QuoteProvider/context/QuoteContext.d.ts +1 -0
  56. package/dist/esm/types/src/components/QuoteProvider/fragments/quoteFragment.d.ts +7 -0
  57. package/dist/esm/types/src/components/QuoteProvider/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
  58. package/dist/esm/types/src/components/QuoteProvider/hooks/useSetQuoteQueryData.d.ts +5 -0
  59. package/dist/esm/types/src/components/QuoteProvider/mutations/quoteRecalculateTaxes.d.ts +11 -0
  60. package/dist/esm/types/src/components/Subscriptions/AddonSubscriptionCards.d.ts +3 -2
  61. package/dist/esm/types/src/components/Subscriptions/SubscriptionsListContainer.d.ts +2 -2
  62. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutBarSummarySection.d.ts +15 -2
  63. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutButton.d.ts +2 -2
  64. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +12 -3
  65. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/FeatureAddonRow_QuoteFragment.d.ts +9 -0
  66. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/useQuoteUpdateFeatureAddon_QuoteFragment.d.ts +8 -0
  67. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/hooks/useQuoteUpdateFeatureAddon.d.ts +9 -0
  68. package/dist/esm/types/src/{graphql → components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons}/mutations/quoteChargeCreate.d.ts +12 -2
  69. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/components/AddonPlanRow.d.ts +1 -0
  70. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/AddonPlanRow_QuoteFragment.d.ts +9 -0
  71. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/useToggleAddonPlan_QuoteFragment.d.ts +13 -0
  72. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/hooks/useToggleAddonQuoteChange.d.ts +9 -0
  73. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeCreate.d.ts +18 -0
  74. package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeDelete.d.ts +15 -0
  75. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteIsLoadingContext.d.ts +5 -0
  76. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteRecalculateTaxesContext.d.ts +6 -0
  77. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
  78. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteDelete.d.ts +12 -0
  79. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteRecalculateTaxes.d.ts +11 -0
  80. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuantityInput.d.ts +10 -1
  81. package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuoteIsLoadingUpdater.d.ts +9 -0
  82. package/dist/esm/types/src/components/Subscriptions/subscriptionsList/SubscriptionsList.d.ts +2 -2
  83. package/dist/esm/types/src/components/Subscriptions/tieredDisplayDropdown/TieredDisplayDropdown.d.ts +3 -1
  84. package/dist/esm/types/src/utils/QueryKeyFactory.d.ts +10 -0
  85. package/package.json +2 -2
  86. package/dist/cjs/types/src/graphql/mutations/billingDetailsUpdate.d.ts +0 -6
  87. package/dist/cjs/types/src/graphql/mutations/quoteAddonCreate.d.ts +0 -7
  88. package/dist/cjs/types/src/graphql/mutations/quoteChangeCreate.d.ts +0 -8
  89. package/dist/cjs/types/src/graphql/mutations/quoteChangeDelete.d.ts +0 -6
  90. package/dist/cjs/types/src/graphql/queries/getBillingDetails.d.ts +0 -6
  91. package/dist/cjs/types/src/hooks/quotes/useQuoteUpdateFeatureAddon.d.ts +0 -7
  92. package/dist/cjs/types/src/hooks/useToggleAddonQuoteChange.d.ts +0 -7
  93. package/dist/esm/types/src/graphql/mutations/billingDetailsUpdate.d.ts +0 -6
  94. package/dist/esm/types/src/graphql/mutations/quoteAddonCreate.d.ts +0 -7
  95. package/dist/esm/types/src/graphql/mutations/quoteChangeCreate.d.ts +0 -8
  96. package/dist/esm/types/src/graphql/mutations/quoteChangeDelete.d.ts +0 -6
  97. package/dist/esm/types/src/graphql/queries/getBillingDetails.d.ts +0 -6
  98. package/dist/esm/types/src/hooks/quotes/useQuoteUpdateFeatureAddon.d.ts +0 -7
  99. 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, ChargeType, PERIOD_LABELS, MODAL_MAX_HEIGHT, DataInterval, SLATE_100 } from '@bunnyapp/common';
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.6.0-beta.23';
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$7 = t(`
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$7, { apiHost, token }, {});
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$A } = Typography;
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$A, { className: "bunny-text-sm bunny-text-gray-400", children: title || 'back' })] }));
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$9 = `
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$9,
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$z } = Typography;
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$z, { className: "bunny-text-slate-400 bunny-text-sm", children: "No payment methods" })] }), jsx(Button, { disabled: true, type: "link" }), buttons] })) }));
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$z, { children: "Cashapp" });
18650
+ return jsx(Text$A, { children: "Cashapp" });
18651
18651
  }
18652
- return (jsxs("div", { children: [jsx(Text$z, { className: "relative -top-0.5", children: "****" }), jsx(Text$z, { children: identifier })] }));
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$z, { children: lodashExports.capitalize(issuer) });
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$6 = t(`
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$6, { apiHost, token }, { accountId });
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$5 = t(`
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$5, { apiHost, token }, { accountId });
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$8 = `
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$8,
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$y } = Typography;
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$y, { children: "DemoPay is for testing only." }), jsx(PaymentMethodFooter, { onSubmit: onSubmit })] }));
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$x } = Typography;
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$x, { children: name })] }), isAch ? (jsx(BankOutlined, { className: "bunny-pr-4" })) : isCard ? (jsx(CardIcon, { className: "bunny-pr-4" })) : (jsx(CardIcon, { className: "bunny-pr-4" }))] }));
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$5 = t(`
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$5, { apiHost, token }, {});
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$4 = t(`
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$4, { apiHost, token }, { id });
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$w } = Typography;
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$w, { 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: {
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$v } = Typography;
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$v, { 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
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$u } = Typography;
21051
+ const { Text: Text$v } = Typography;
21040
21052
  const TransactionDate = ({ date }) => {
21041
- return jsx(Text$u, { className: "bunny-text-sm", children: formatDate(date) });
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$t } = Typography;
21097
+ const { Text: Text$u } = Typography;
21086
21098
  const TransactionsEmptyState = () => {
21087
21099
  const { noTransactionsMessage } = useContext(TransactionsListContext);
21088
- return (jsx(Text$t, { className: "bunny-flex bunny-justify-center bunny-p-4 bunny-text-base", children: noTransactionsMessage || 'There are no transactions' }));
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$s } = Typography;
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$s, { className: "bunny-text-slate-400", style: { fontSize: '11px' }, children: transaction.transactionable.number }));
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$r } = Typography;
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$r, { 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$r, { children: lodashExports.capitalize(transaction.kind.toLowerCase()) }), jsx(TransactionRowTitle, { transaction: transaction })] }) })), showAccountName && (jsx(TransactionGridCell, { right: false, children: jsx(Text$r, { 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$r, { 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));
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$q } = Typography;
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$q, { 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$q, { children: (_a = transaction.account) === null || _a === void 0 ? void 0 : _a.name }), showAccountName && showDate && jsx(Text$q, { children: "\u00B7" }), showDate && (jsx(TransactionDate, { date: transactionDateToDisplay(transaction, transactionDateType) })), showDate && showAmount && jsx(Text$q, { children: "\u00B7" }), showAmount && (jsx(Text$q, { 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));
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$p } = Typography;
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$p, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsx("div", {}) // Empty div so justify-between works
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$7 = () => `
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$7(),
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$6 = () => `
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$6(),
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$5 = () => `
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$5(),
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
- function canEditChargeQuantity(charge) {
21695
- if (!charge)
21696
- return false;
21697
- if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
21698
- return false;
21699
- if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
21700
- return false;
21701
- return true;
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 MUTATION$4 = `{
21729
- currentUser {
21730
- taxationRequiredAccountFields
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
- const BunnyFooterIcon = ({ color }) => {
21746
- 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" }) }) })] }));
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
- const { Text: Text$o } = Typography;
21750
- const Footer = ({ className }) => {
21751
- const token = useToken();
21752
- const { currentUser } = useCurrentUserData(token);
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 BunnyMarketingLink = () => {
21758
- const [isHovered, setIsHovered] = useState(false);
21759
- const isMobile = useIsMobile$1();
21760
- 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 }) })] }) }) }));
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 StyedLink = styled.a `
21763
- color: ${SLATE_400};
21764
- transition: color 0.3s;
21765
- &:hover {
21766
- color: ${SLATE_500};
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
- const vars = { couponCode, quoteChangeId };
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 MUTATION$2 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
21804
- quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
21805
- errors
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
- const COUPONS_QUERY = (filter) => `
21825
- query Coupons {
21826
- coupons(filter: ${filter ? `"${filter}"` : 'null'}) {
21827
- totalCount
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
- const getCoupons = async ({ token, apiHost, filter, }) => {
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$3 = useErrorNotification();
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$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error adding coupon');
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$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error removing coupon');
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$1 = `
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$1,
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(Fragment, { 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 &&
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)" }))] })) : (jsx(PaymentFormWrapper, { setMaxHeight: false, children: 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("div", { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] }) })) }));
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: '350px',
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
- const updatedQuote = await quoteRecalculateTaxes({
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
- const QuoteContext = createContext({});
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$n } = Typography;
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$n, { 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: {
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$n, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
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, upgradingSubscription } = useContext(SubscriptionsContext);
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), open: payModalVisible, selectedPriceList: selectedPriceList }), jsx(Checkout, { onCancel: () => setPayModalVisible(false), onFail: error => handlePortalErrors === null || handlePortalErrors === void 0 ? void 0 : handlePortalErrors(error), onSuccess: handleCheckoutSuccess, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: isUpdatingQuote })] }));
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
- `, [QuoteFields_QuoteFragment, PlanPickerCheckoutBar_QuoteFragment]);
22623
-
22624
- // Deprecated: Keeping this for now because its used in many places
22625
- const QUOTE_FIELDS = (removeFormattedQuoteField) => `
22626
- fragment QuoteFields on Quote {
22627
- accountId
22628
- amount
22629
- amountDue
22630
- smallUnitAmountDue
22631
- currencyId
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$3 = t(`
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$3, { apiHost, token }, { id, removeFormattedQuoteField });
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$4 = t(`
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$4, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
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$3 = t(`
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$3, { apiHost, token }, { quoteChargeId, quantity });
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$2 = t(`
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$2, { apiHost, token }, { subscriptionIds });
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 createQuote = useMutation({
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
- // The set charge id is used to disable all other quantity inputs
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.cancel();
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 debouncedQuantityUpdate = useCallback(lodashExports.debounce((priceListChargeId, quantityDelta, quantity, subscriptionId, quote, quoteId) => {
23358
- var _a, _b, _c;
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.mutate(subscriptionId);
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.mutate({
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 (jsx(Fragment, { children: jsx(Input, { className: "bunny-text-right", disabled: quantityDisabled, onChange: e => {
23395
- onChangeQuantity(e.target.value);
23396
- }, style: { width: '96px' }, value: value }) }));
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
- return (jsx(QuoteIdProvider, { children: jsx(QuantityDrawerContent, { subscriptions: subscriptions, quantityDrawerOpen: quantityDrawerOpen, setQuantityDrawerOpen: setQuantityDrawerOpen, handlePortalErrors: handlePortalErrors, setShowInactive: setShowInactive }) }));
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: isInTrial ? 'Upgrade from trial' : isTrialExpired ? 'Upgrade' : 'Change plan' })), !arePlansAvailable && isInTrial && jsx(Tag, { color: "warning", children: "Cannot upgrade" })] }));
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$2 = t(`
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$2, { apiHost, token }, { productId });
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 (jsx("div", { className: "rounded border border-solid border-slate-200 bg-white overflow-hidden", children: jsx(StyledTable, { columns: [
23968
- {
23969
- dataIndex: 'starts',
23970
- title: 'From # of units',
23971
- align: 'right',
23972
- render: (_, record, index) => {
23973
- record = record;
23974
- const nextRecord = priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers[index + 1];
23975
- const starts = record.starts;
23976
- const ends = (nextRecord === null || nextRecord === void 0 ? void 0 : nextRecord.starts) ? nextRecord.starts - 1 : '';
23977
- return (jsxs(Fragment, { children: [formatNumber(starts, 0), " -", ' ', typeof ends === 'number' ? formatNumber(ends, 0) : ''] }));
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
- dataIndex: 'price',
23982
- title: 'Unit price',
23983
- align: 'right',
23984
- render: value => {
23985
- return jsx(Fragment, { children: formatCurrency$1(value, currencyId, priceDecimals) });
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$1 = t(`
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$1, { apiHost, token }, { id, includeHtmlField });
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$1 = t(`
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$1, {
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
- var _a;
24534
- queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
24535
- objectName: 'editingQuote',
24536
- id: (_a = quote === null || quote === void 0 ? void 0 : quote.id) !== null && _a !== void 0 ? _a : undefined,
24537
- token,
24538
- }), quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote);
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
- throw new Error('Quote change is undefined');
24710
+ console.error('Quote change is undefined');
24711
+ return;
24544
24712
  }
24545
24713
  if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
24546
- throw new Error('Quote ID is undefined');
24714
+ console.error('Quote ID is undefined');
24715
+ return;
24547
24716
  }
24548
24717
  if (!(selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.id)) {
24549
- throw new Error('Quote change ID is undefined');
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.map(featureId => {
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
- throw new Error('Quantity is undefined');
24736
+ console.error('Quantity is undefined');
24737
+ return;
24566
24738
  }
24567
24739
  if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id)) {
24568
- throw new Error('Quote charge for featureId is undefined');
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 useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
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 queryClient = useQueryClient();
25670
+ const { setQuoteQueryData } = useSetQuoteQueryData();
25671
+ // Read fragments
25672
+ const quote = readFragment(useQuoteUpdateFeatureAddon_QuoteFragment, maskedQuote);
25523
25673
  const addedQuoteChargeId = useRef();
25524
25674
  function handleAddFeatureAddon() {
25525
- quoteChargeCreateMutation();
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: async () => {
25534
- if (!token)
25535
- throw new Error('Token is required');
25536
- if (!quote)
25537
- throw new Error('Editing quote is required');
25538
- const quoteChangeId = findQuoteChangeForFeatureAddon(quote);
25539
- if (!quoteChangeId)
25540
- throw new Error('No available quote change for feature add-on');
25541
- const quoteCharge = await quoteChargeCreate({
25542
- quoteChangeId: quoteChangeId.id,
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
- queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
25567
- objectName: 'editingQuote',
25568
- id: quote === null || quote === void 0 ? void 0 : quote.id,
25569
- token,
25570
- }), quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
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 { quote, selectedPriceList } = useContext(QuoteContext);
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 QUOTE_CHANGE_CREATE = `
25869
- ${QUOTE_FIELDS()}
25870
- mutation QuoteChangeCreate(
25871
- $quoteId: ID!
25872
- $priceListId: ID!
25873
- $parentQuoteChangeId: ID!
25874
- ) {
25875
- quoteChangeCreate(
25876
- quoteId: $quoteId
25877
- priceListId: $priceListId
25878
- parentQuoteChangeId: $parentQuoteChangeId
25879
- ) {
25880
- errors
25881
- quoteChange {
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
- var _a;
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 QUOTE_CHANGE_DELETE = `
25910
- ${QUOTE_FIELDS()}
25911
- mutation QuoteChangeDelete($id: ID!) {
25912
- quoteChangeDelete(id: $id) {
25913
- errors
25914
- quoteChange {
25915
- quote {
25916
- ...QuoteFields
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
- var _a;
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 = (quote, addonPriceListId, selectedPriceList, setIsAddonPlanLoading) => {
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
- return quote === null || quote === void 0 ? void 0 : quote.quoteChanges.find(qc => qc.priceList.id === selectedPriceList.id);
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: (quoteChangeCreate) => {
26074
+ onSuccess: quoteChangeCreate => {
26075
+ var _a;
25950
26076
  isAdded.current = true;
25951
- const updatedQuote = quoteChangeCreate.quoteChange.quote;
25952
- queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
25953
- objectName: 'editingQuote',
25954
- id: quote === null || quote === void 0 ? void 0 : quote.id,
25955
- token,
25956
- }), updatedQuote);
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: (quoteChangeDelete) => {
26089
+ onSuccess: quoteChangeDelete => {
26090
+ var _a;
25962
26091
  isAdded.current = false;
25963
- const updatedQuote = quoteChangeDelete.quoteChange.quote;
25964
- queryClient.setQueryData(QueryKeyFactory$1.default.createObjectKey({
25965
- objectName: 'editingQuote',
25966
- id: quote === null || quote === void 0 ? void 0 : quote.id,
25967
- token,
25968
- }), updatedQuote);
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
- const quoteChange = quote === null || quote === void 0 ? void 0 : quote.quoteChanges.find(qc => qc.priceList.id === addonPriceListId);
25988
- if (!quoteChange) {
25989
- throw new Error('Quote change not found');
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
- 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: (_b = addonPriceList.plan) === null || _b === void 0 ? void 0 : _b.name }), jsx(PriceListCardDescription, { description: (_d = (_c = addonPriceList.plan) === null || _c === void 0 ? void 0 : _c.description) !== null && _d !== void 0 ? _d : '' }), 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((_f = (_e = addonPriceList.plan) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : ''), loading: isPending && !switchDisabled, checked: addedQuoteChange || isPurchased, onChange: (checked) => {
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
- return (((_a = priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists) === null || _a === void 0 ? void 0 : _a.filter(priceList => periodMonthsConverter(priceList.periodMonths) === selectedBillingPeriod &&
26209
- priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id)).filter(priceList => priceList.plan.addon !== true)) || []);
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 MUTATION = `
26906
- mutation BillingDetailsUpdate(
26907
- $attributes: BillingDetailsAttributes!) {
26908
- billingDetailsUpdate(
26909
- attributes: $attributes
26910
- ) {
26911
- billingDetails {
26912
- billingCity
26913
- billingContact {
26914
- email
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 billingDetailsUpdate = async ({ attributes, token, apiHost, }) => {
26928
- var _a;
26929
- const vars = { attributes };
26930
- const response = await gqlRequest({
26931
- query: MUTATION,
26932
- token,
26933
- vars,
26934
- apiHost,
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 errors = (_a = response === null || response === void 0 ? void 0 : response.billingDetailsUpdate) === null || _a === void 0 ? void 0 : _a.errors;
26937
- if (errors)
26938
- throw errors;
26939
- return response.billingDetailsUpdate;
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 billingDetailsQuery = () => `
26943
- query BillingDetails {
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 getBillingDetails = async ({ token, apiHost }) => {
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 gqlRequest({
26963
- query: billingDetailsQuery(),
26964
- token,
26965
- apiHost,
26966
- });
26967
- if (response === null || response === void 0 ? void 0 : response.errors) {
26968
- throw new Error((_a = response === null || response === void 0 ? void 0 : response.errors[0]) === null || _a === void 0 ? void 0 : _a.message);
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
- return response === null || response === void 0 ? void 0 : response.billingDetails;
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: billingDetails, isLoading: isLoadingBillingDetails } = useQuery({
26989
- queryKey: QueryKeyFactory$1.default.billingDetailsKey({ token }),
26990
- queryFn: () => getBillingDetails({ token, apiHost }),
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: updateBillingDetails, isPending: isUpdatingBillingDetails } = useMutation({
27256
+ const { mutate: updateAccount, isPending: isUpdatingAccount } = useMutation({
26993
27257
  mutationFn: async (changedFormData) => {
26994
- const updatedBillingDetails = await billingDetailsUpdate({
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$1.default.billingDetailsKey({ token }), (old) => {
27009
- return {
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$1.default.taxationRequiredAccountFieldsKey({
27285
+ queryKey: QueryKeyFactory.taxationRequiredAccountFieldsKey({
27020
27286
  token,
27021
27287
  }),
27022
27288
  });
27023
27289
  },
27024
27290
  });
27025
- // Set form values when billing details are loaded
27291
+ // Set form values when account is loaded
27026
27292
  useEffect(() => {
27027
- var _a;
27028
- if (billingDetails) {
27293
+ if (account) {
27029
27294
  form.setFieldsValue({
27030
- billingStreet: billingDetails.billingStreet,
27031
- billingCity: billingDetails.billingCity,
27032
- billingZip: billingDetails.billingZip,
27033
- billingState: billingDetails.billingState,
27034
- billingCountry: billingDetails.billingCountry,
27035
- billingContactEmail: (_a = billingDetails.billingContact) === null || _a === void 0 ? void 0 : _a.email,
27036
- taxNumber: billingDetails.taxNumber,
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
- }, [billingDetails]);
27305
+ }, [account]);
27040
27306
  useEffect(() => {
27041
27307
  form.validateFields({ validateOnly: true });
27042
27308
  const isFormEdited = () => {
27043
- var _a;
27044
- if (!billingDetails)
27309
+ if (!account)
27045
27310
  return false;
27046
27311
  const currentValues = form.getFieldsValue();
27047
27312
  const accountValues = {
27048
- billingStreet: billingDetails.billingStreet,
27049
- billingCity: billingDetails.billingCity,
27050
- billingZip: billingDetails.billingZip,
27051
- billingState: billingDetails.billingState,
27052
- billingCountry: billingDetails.billingCountry,
27053
- billingContactEmail: (_a = billingDetails.billingContact) === null || _a === void 0 ? void 0 : _a.email,
27054
- taxNumber: billingDetails.taxNumber,
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(currentValues).some(key => {
27322
+ return Object.keys(accountValues).some(key => {
27057
27323
  const value = accountValues[key];
27058
- return currentValues[key] !== value;
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, billingDetails]);
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
- updateBillingDetails(form.getFieldsValue());
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
- return (jsx("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: jsxs("div", { className: "bunny-px-4", children: [jsxs(Skeleton, { loading: isLoadingBillingDetails, children: [jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (billingDetails === null || billingDetails === void 0 ? void 0 : billingDetails.name) || 'No company name' }) }), jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingBillingDetails, 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: [
27091
- {
27092
- required: false,
27093
- },
27094
- ], 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) => {
27095
- var _a, _b;
27096
- return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
27097
- ((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
27098
- } }) }) })] }), jsx(Form.Item, { label: "Email", name: "billingContactEmail", rules: [
27099
- {
27100
- required: true,
27101
- message: 'Email is required',
27102
- type: 'email',
27103
- },
27104
- ], children: jsx(Input, {}) }), 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 || isUpdatingBillingDetails, className: "bunny-w-full bunny-mt-4", type: "primary", onClick: saveBillingDetails, children: "Save" })] }) }));
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, }) => {