useOrganizationRestrictions.ts 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import type { ReactNode } from 'react'
  2. import { useIsFeatureEnabled } from './useIsFeatureEnabled'
  3. import { RESTRICTION_MESSAGES } from '@/components/interfaces/Organization/restriction.constants'
  4. import { useOverdueInvoicesQuery } from '@/data/invoices/invoices-overdue-query'
  5. import { useOrganizationsQuery } from '@/data/organizations/organizations-query'
  6. import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
  7. export type WarningBannerProps = {
  8. variant: 'danger' | 'warning' | 'note'
  9. title: string
  10. description: ReactNode
  11. }
  12. /**
  13. * Compute billing-related restriction banners for the currently selected organization.
  14. *
  15. * The hook examines billing feature availability, overdue invoices, organization billing data,
  16. * and restriction status to produce an ordered list of warning/danger banner props.
  17. *
  18. * @returns An object containing:
  19. * - `warnings`: an array of `WarningBannerProps` to display for the selected organization (may be empty).
  20. * - `org`: the selected organization data (may be `undefined`).
  21. */
  22. export function useOrganizationRestrictions() {
  23. const { data: org } = useSelectedOrganizationQuery()
  24. const { data: overdueInvoices } = useOverdueInvoicesQuery()
  25. const { data: organizations } = useOrganizationsQuery()
  26. const warnings: WarningBannerProps[] = []
  27. const billingEnabled = useIsFeatureEnabled('billing:all')
  28. if (!billingEnabled) {
  29. return { warnings, org }
  30. }
  31. const overdueInvoicesFromOtherOrgs = overdueInvoices?.filter(
  32. (invoice) => invoice.organization_id !== org?.id
  33. )
  34. const thisOrgHasOverdueInvoices = overdueInvoices?.filter(
  35. (invoice) => invoice.organization_id === org?.id
  36. )
  37. if (thisOrgHasOverdueInvoices?.length) {
  38. warnings.push({
  39. variant: 'danger',
  40. title: RESTRICTION_MESSAGES.OVERDUE_INVOICES.title,
  41. description: RESTRICTION_MESSAGES.OVERDUE_INVOICES.description(org?.slug ?? 'default'),
  42. })
  43. }
  44. if (overdueInvoicesFromOtherOrgs?.length) {
  45. const otherOrgSlug = organizations?.find(
  46. (o) => o.id === overdueInvoicesFromOtherOrgs[0].organization_id
  47. )?.slug
  48. warnings.push({
  49. variant: 'danger',
  50. title: RESTRICTION_MESSAGES.OVERDUE_INVOICES_FROM_OTHER_ORGS.title,
  51. description: RESTRICTION_MESSAGES.OVERDUE_INVOICES_FROM_OTHER_ORGS.description(
  52. otherOrgSlug ?? org?.slug ?? 'default'
  53. ),
  54. })
  55. }
  56. if (org?.restriction_status === 'grace_period') {
  57. warnings.push({
  58. variant: 'warning',
  59. title: RESTRICTION_MESSAGES.GRACE_PERIOD.title,
  60. description: RESTRICTION_MESSAGES.GRACE_PERIOD.description(
  61. org?.restriction_data?.['grace_period_end'] ?? '',
  62. org.slug
  63. ),
  64. })
  65. }
  66. if (org?.restriction_status === 'grace_period_over') {
  67. warnings.push({
  68. variant: 'warning',
  69. title: RESTRICTION_MESSAGES.GRACE_PERIOD_OVER.title,
  70. description: RESTRICTION_MESSAGES.GRACE_PERIOD_OVER.description(org.slug),
  71. })
  72. }
  73. if (org?.restriction_status === 'restricted') {
  74. warnings.push({
  75. variant: 'danger',
  76. title: RESTRICTION_MESSAGES.RESTRICTED.title,
  77. description: RESTRICTION_MESSAGES.RESTRICTED.description(org.slug),
  78. })
  79. }
  80. return { warnings, org }
  81. }