@carlonicora/nextjs-jsonapi 1.14.0 → 1.16.0

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 (279) hide show
  1. package/dist/{ApiResponseInterface-B4QdWh-y.d.mts → ApiResponseInterface-BvWIeLkq.d.ts} +2 -1
  2. package/dist/{ApiResponseInterface-QLDnxLA9.d.ts → ApiResponseInterface-CAbw0sv7.d.mts} +2 -1
  3. package/dist/{BlockNoteEditor-436ZHDY3.mjs → BlockNoteEditor-HFX7Z5BQ.mjs} +5 -5
  4. package/dist/{BlockNoteEditor-WCK43JHX.js → BlockNoteEditor-MBFDWP7X.js} +15 -15
  5. package/dist/{BlockNoteEditor-WCK43JHX.js.map → BlockNoteEditor-MBFDWP7X.js.map} +1 -1
  6. package/dist/JsonApiRequest-45CLE65I.js +24 -0
  7. package/dist/{JsonApiRequest-FXZCYIER.js.map → JsonApiRequest-45CLE65I.js.map} +1 -1
  8. package/dist/{JsonApiRequest-HFWXMKMA.mjs → JsonApiRequest-6IPS3DZJ.mjs} +2 -2
  9. package/dist/{chunk-R6K76UTR.js → chunk-2AZLCF6D.js} +1687 -183
  10. package/dist/chunk-2AZLCF6D.js.map +1 -0
  11. package/dist/{chunk-2FCG3K64.mjs → chunk-5RAUCUAA.mjs} +3722 -396
  12. package/dist/chunk-5RAUCUAA.mjs.map +1 -0
  13. package/dist/{chunk-TGBXBUWM.mjs → chunk-BCKYJQ3K.mjs} +8 -1
  14. package/dist/chunk-BCKYJQ3K.mjs.map +1 -0
  15. package/dist/{chunk-A333VMBO.mjs → chunk-BCQSE3EU.mjs} +1654 -150
  16. package/dist/chunk-BCQSE3EU.mjs.map +1 -0
  17. package/dist/{chunk-FPZPD4JI.js → chunk-GPGJNTHP.js} +17 -10
  18. package/dist/chunk-GPGJNTHP.js.map +1 -0
  19. package/dist/{chunk-45QMJETP.js → chunk-ONB2DAIV.js} +4090 -764
  20. package/dist/chunk-ONB2DAIV.js.map +1 -0
  21. package/dist/{chunk-SJIVGCNM.mjs → chunk-POKIJ56Q.mjs} +7 -2
  22. package/dist/chunk-POKIJ56Q.mjs.map +1 -0
  23. package/dist/{chunk-6YD42BP6.js → chunk-R5QSSISB.js} +14 -9
  24. package/dist/chunk-R5QSSISB.js.map +1 -0
  25. package/dist/client/index.d.mts +5 -5
  26. package/dist/client/index.d.ts +5 -5
  27. package/dist/client/index.js +7 -5
  28. package/dist/client/index.js.map +1 -1
  29. package/dist/client/index.mjs +6 -4
  30. package/dist/components/index.d.mts +253 -9
  31. package/dist/components/index.d.ts +253 -9
  32. package/dist/components/index.js +83 -5
  33. package/dist/components/index.js.map +1 -1
  34. package/dist/components/index.mjs +82 -4
  35. package/dist/{config-eceYM5kN.d.ts → config-CWsTwnsK.d.mts} +7 -2
  36. package/dist/{config-C5tGGrYf.d.mts → config-DEaUbBqR.d.ts} +7 -2
  37. package/dist/{content.interface-TB2MfJGs.d.ts → content.interface-D_4b4RQt.d.ts} +1 -1
  38. package/dist/{content.interface-CxBBC7ec.d.mts → content.interface-Dk4UZcJM.d.mts} +1 -1
  39. package/dist/contexts/index.d.mts +2 -2
  40. package/dist/contexts/index.d.ts +2 -2
  41. package/dist/contexts/index.js +5 -5
  42. package/dist/contexts/index.mjs +4 -4
  43. package/dist/core/index.d.mts +528 -22
  44. package/dist/core/index.d.ts +528 -22
  45. package/dist/core/index.js +53 -3
  46. package/dist/core/index.js.map +1 -1
  47. package/dist/core/index.mjs +52 -2
  48. package/dist/index.d.mts +7 -7
  49. package/dist/index.d.ts +7 -7
  50. package/dist/index.js +56 -4
  51. package/dist/index.js.map +1 -1
  52. package/dist/index.mjs +55 -3
  53. package/dist/{notification.interface-lG6UpTpt.d.mts → notification.interface-BllkURRm.d.mts} +1 -2
  54. package/dist/{notification.interface-lG6UpTpt.d.ts → notification.interface-BllkURRm.d.ts} +1 -2
  55. package/dist/{s3.service-DP_hsssD.d.mts → s3.service-BEfGqho0.d.ts} +20 -2
  56. package/dist/{s3.service-Dq-PTUNa.d.ts → s3.service-DIQRYe93.d.mts} +20 -2
  57. package/dist/scripts/generate-web-module/generator.d.ts.map +1 -1
  58. package/dist/scripts/generate-web-module/generator.js +66 -0
  59. package/dist/scripts/generate-web-module/generator.js.map +1 -1
  60. package/dist/scripts/generate-web-module/templates/data/interface.template.js +8 -1
  61. package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -1
  62. package/dist/scripts/generate-web-module/templates/data/model.template.js +26 -3
  63. package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -1
  64. package/dist/scripts/generate-web-module/templates/index.d.ts +8 -0
  65. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
  66. package/dist/scripts/generate-web-module/templates/index.js +18 -1
  67. package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
  68. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts +7 -0
  69. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts.map +1 -0
  70. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js +141 -0
  71. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js.map +1 -0
  72. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts +7 -0
  73. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts.map +1 -0
  74. package/dist/scripts/generate-web-module/templates/project/env.template.js +110 -0
  75. package/dist/scripts/generate-web-module/templates/project/env.template.js.map +1 -0
  76. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts +7 -0
  77. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts.map +1 -0
  78. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js +101 -0
  79. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js.map +1 -0
  80. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts +7 -0
  81. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts.map +1 -0
  82. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js +66 -0
  83. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js.map +1 -0
  84. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts +7 -0
  85. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts.map +1 -0
  86. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js +257 -0
  87. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js.map +1 -0
  88. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts +7 -0
  89. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts.map +1 -0
  90. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js +124 -0
  91. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js.map +1 -0
  92. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts +7 -0
  93. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts.map +1 -0
  94. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js +78 -0
  95. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js.map +1 -0
  96. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts +7 -0
  97. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts.map +1 -0
  98. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js +75 -0
  99. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js.map +1 -0
  100. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +1 -1
  101. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
  102. package/dist/server/index.d.mts +4 -4
  103. package/dist/server/index.d.ts +4 -4
  104. package/dist/server/index.js +12 -12
  105. package/dist/server/index.mjs +2 -2
  106. package/dist/stripe-subscription.interface-C63L6hVg.d.mts +226 -0
  107. package/dist/stripe-subscription.interface-CUvNDvw5.d.ts +226 -0
  108. package/dist/{useSocket-Bua6MwLi.d.mts → useSocket-BpenBR2z.d.mts} +1 -1
  109. package/dist/{useSocket-D5dhUp4m.d.ts → useSocket-D-QYA0Sr.d.ts} +1 -1
  110. package/package.json +9 -1
  111. package/scripts/generate-web-module/generator.ts +83 -0
  112. package/scripts/generate-web-module/templates/data/interface.template.ts +7 -1
  113. package/scripts/generate-web-module/templates/data/model.template.ts +28 -5
  114. package/scripts/generate-web-module/templates/index.ts +10 -0
  115. package/scripts/generate-web-module/templates/project/bootstrapper.template.ts +108 -0
  116. package/scripts/generate-web-module/templates/project/env.template.ts +77 -0
  117. package/scripts/generate-web-module/templates/project/main-layout.template.tsx +68 -0
  118. package/scripts/generate-web-module/templates/project/middleware-env.template.ts +33 -0
  119. package/scripts/generate-web-module/templates/project/settings-container.template.tsx +224 -0
  120. package/scripts/generate-web-module/templates/project/settings-context.template.tsx +91 -0
  121. package/scripts/generate-web-module/templates/project/settings-module-page.template.tsx +45 -0
  122. package/scripts/generate-web-module/templates/project/settings-page.template.tsx +42 -0
  123. package/scripts/generate-web-module/types/template-data.interface.ts +1 -1
  124. package/src/client/config.ts +9 -0
  125. package/src/components/index.ts +7 -0
  126. package/src/core/abstracts/AbstractApiData.ts +79 -16
  127. package/src/core/abstracts/AbstractService.ts +104 -0
  128. package/src/core/endpoint/EndpointCreator.ts +7 -4
  129. package/src/core/index.ts +12 -4
  130. package/src/core/interfaces/ApiResponseInterface.ts +1 -0
  131. package/src/core/registry/ModuleRegistry.ts +11 -2
  132. package/src/core/utils/translateResponse.ts +17 -0
  133. package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +97 -0
  134. package/src/features/billing/components/cards/CustomerInfoCard.tsx +112 -0
  135. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +114 -0
  136. package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +119 -0
  137. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +146 -0
  138. package/src/features/billing/components/cards/index.ts +5 -0
  139. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +427 -0
  140. package/src/features/billing/components/containers/index.ts +1 -0
  141. package/src/features/billing/components/index.ts +6 -0
  142. package/src/features/billing/components/modals/BillingDetailModal.tsx +36 -0
  143. package/src/features/billing/components/modals/index.ts +1 -0
  144. package/src/features/billing/components/providers/StripeProvider.tsx +48 -0
  145. package/src/features/billing/components/providers/index.ts +1 -0
  146. package/src/features/billing/components/utils/currency.ts +49 -0
  147. package/src/features/billing/components/utils/date.ts +21 -0
  148. package/src/features/billing/components/utils/index.ts +2 -0
  149. package/src/features/billing/components/widgets/BillingAlertBanner.tsx +63 -0
  150. package/src/features/billing/components/widgets/index.ts +1 -0
  151. package/src/features/billing/data/Billing.ts +17 -0
  152. package/src/features/billing/data/billing.service.ts +58 -0
  153. package/src/features/billing/data/index.ts +5 -0
  154. package/src/features/billing/index.ts +3 -0
  155. package/src/features/billing/modules/billing.module.ts +9 -0
  156. package/src/features/billing/modules/index.ts +1 -0
  157. package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +79 -0
  158. package/src/features/billing/stripe-customer/components/containers/index.ts +1 -0
  159. package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +151 -0
  160. package/src/features/billing/stripe-customer/components/details/index.ts +1 -0
  161. package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +186 -0
  162. package/src/features/billing/stripe-customer/components/forms/index.ts +1 -0
  163. package/src/features/billing/stripe-customer/components/index.ts +4 -0
  164. package/src/features/billing/stripe-customer/components/lists/PaymentMethodsList.tsx +19 -0
  165. package/src/features/billing/stripe-customer/components/lists/index.ts +1 -0
  166. package/src/features/billing/stripe-customer/data/index.ts +5 -0
  167. package/src/features/billing/stripe-customer/data/payment-method.interface.ts +27 -0
  168. package/src/features/billing/stripe-customer/data/payment-method.ts +119 -0
  169. package/src/features/billing/stripe-customer/data/stripe-customer.interface.ts +16 -0
  170. package/src/features/billing/stripe-customer/data/stripe-customer.service.ts +128 -0
  171. package/src/features/billing/stripe-customer/data/stripe-customer.ts +71 -0
  172. package/src/features/billing/stripe-customer/index.ts +3 -0
  173. package/src/features/billing/stripe-customer/stripe-customer.module.ts +9 -0
  174. package/src/features/billing/stripe-customer/stripe-payment-method.module.ts +9 -0
  175. package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +66 -0
  176. package/src/features/billing/stripe-invoice/components/containers/index.ts +1 -0
  177. package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +172 -0
  178. package/src/features/billing/stripe-invoice/components/details/index.ts +1 -0
  179. package/src/features/billing/stripe-invoice/components/index.ts +4 -0
  180. package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +84 -0
  181. package/src/features/billing/stripe-invoice/components/lists/index.ts +1 -0
  182. package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +41 -0
  183. package/src/features/billing/stripe-invoice/components/widgets/index.ts +1 -0
  184. package/src/features/billing/stripe-invoice/data/index.ts +3 -0
  185. package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +65 -0
  186. package/src/features/billing/stripe-invoice/data/stripe-invoice.service.ts +64 -0
  187. package/src/features/billing/stripe-invoice/data/stripe-invoice.ts +177 -0
  188. package/src/features/billing/stripe-invoice/index.ts +2 -0
  189. package/src/features/billing/stripe-invoice/stripe-invoice.module.ts +9 -0
  190. package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +304 -0
  191. package/src/features/billing/stripe-price/components/forms/index.ts +1 -0
  192. package/src/features/billing/stripe-price/components/index.ts +2 -0
  193. package/src/features/billing/stripe-price/components/lists/PricesList.tsx +283 -0
  194. package/src/features/billing/stripe-price/components/lists/index.ts +1 -0
  195. package/src/features/billing/stripe-price/data/index.ts +3 -0
  196. package/src/features/billing/stripe-price/data/stripe-price.interface.ts +48 -0
  197. package/src/features/billing/stripe-price/data/stripe-price.service.ts +123 -0
  198. package/src/features/billing/stripe-price/data/stripe-price.ts +156 -0
  199. package/src/features/billing/stripe-price/index.ts +2 -0
  200. package/src/features/billing/stripe-price/stripe-price.module.ts +9 -0
  201. package/src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx +86 -0
  202. package/src/features/billing/stripe-product/components/containers/index.ts +1 -0
  203. package/src/features/billing/stripe-product/components/forms/ProductEditor.tsx +100 -0
  204. package/src/features/billing/stripe-product/components/forms/index.ts +1 -0
  205. package/src/features/billing/stripe-product/components/index.ts +3 -0
  206. package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +206 -0
  207. package/src/features/billing/stripe-product/components/lists/index.ts +1 -0
  208. package/src/features/billing/stripe-product/data/index.ts +3 -0
  209. package/src/features/billing/stripe-product/data/stripe-product.interface.ts +18 -0
  210. package/src/features/billing/stripe-product/data/stripe-product.service.ts +112 -0
  211. package/src/features/billing/stripe-product/data/stripe-product.ts +74 -0
  212. package/src/features/billing/stripe-product/index.ts +2 -0
  213. package/src/features/billing/stripe-product/stripe-product.module.ts +9 -0
  214. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +304 -0
  215. package/src/features/billing/stripe-subscription/components/containers/index.ts +1 -0
  216. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +223 -0
  217. package/src/features/billing/stripe-subscription/components/details/index.ts +1 -0
  218. package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +116 -0
  219. package/src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx +331 -0
  220. package/src/features/billing/stripe-subscription/components/forms/index.ts +2 -0
  221. package/src/features/billing/stripe-subscription/components/index.ts +5 -0
  222. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +104 -0
  223. package/src/features/billing/stripe-subscription/components/lists/index.ts +1 -0
  224. package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +95 -0
  225. package/src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx +110 -0
  226. package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +41 -0
  227. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +60 -0
  228. package/src/features/billing/stripe-subscription/components/widgets/index.ts +4 -0
  229. package/src/features/billing/stripe-subscription/data/index.ts +3 -0
  230. package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +66 -0
  231. package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +193 -0
  232. package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +135 -0
  233. package/src/features/billing/stripe-subscription/hooks/index.ts +1 -0
  234. package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +111 -0
  235. package/src/features/billing/stripe-subscription/index.ts +5 -0
  236. package/src/features/billing/stripe-subscription/stripe-subscription.module.ts +9 -0
  237. package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +109 -0
  238. package/src/features/billing/stripe-usage/components/containers/index.ts +1 -0
  239. package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +90 -0
  240. package/src/features/billing/stripe-usage/components/details/index.ts +1 -0
  241. package/src/features/billing/stripe-usage/components/index.ts +4 -0
  242. package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +72 -0
  243. package/src/features/billing/stripe-usage/components/lists/index.ts +1 -0
  244. package/src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx +19 -0
  245. package/src/features/billing/stripe-usage/components/widgets/index.ts +1 -0
  246. package/src/features/billing/stripe-usage/data/index.ts +3 -0
  247. package/src/features/billing/stripe-usage/data/stripe-usage.interface.ts +55 -0
  248. package/src/features/billing/stripe-usage/data/stripe-usage.service.ts +129 -0
  249. package/src/features/billing/stripe-usage/data/stripe-usage.ts +70 -0
  250. package/src/features/billing/stripe-usage/index.ts +2 -0
  251. package/src/features/billing/stripe-usage/stripe-usage.module.ts +9 -0
  252. package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
  253. package/src/features/company/components/forms/CompanyLicense.tsx +4 -4
  254. package/src/features/company/contexts/CompanyContext.tsx +2 -2
  255. package/src/features/feature/components/forms/FormFeatures.tsx +13 -106
  256. package/src/features/feature/data/feature.interface.ts +1 -1
  257. package/src/features/feature/data/feature.ts +4 -4
  258. package/src/features/index.ts +7 -0
  259. package/src/features/module/data/module.interface.ts +0 -1
  260. package/src/features/module/data/module.ts +0 -6
  261. package/src/features/user/components/lists/ContributorsList.tsx +2 -2
  262. package/src/features/user/components/widgets/UserAvatar.tsx +1 -1
  263. package/src/index.ts +1 -1
  264. package/src/shadcnui/custom/link.tsx +16 -6
  265. package/src/utils/blocknote-diff.util.ts +2 -1
  266. package/src/utils/blocknote-word-diff-renderer.util.ts +8 -7
  267. package/dist/AuthComponent-hxOPs9o8.d.mts +0 -11
  268. package/dist/AuthComponent-hxOPs9o8.d.ts +0 -11
  269. package/dist/JsonApiRequest-FXZCYIER.js +0 -24
  270. package/dist/chunk-2FCG3K64.mjs.map +0 -1
  271. package/dist/chunk-45QMJETP.js.map +0 -1
  272. package/dist/chunk-6YD42BP6.js.map +0 -1
  273. package/dist/chunk-A333VMBO.mjs.map +0 -1
  274. package/dist/chunk-FPZPD4JI.js.map +0 -1
  275. package/dist/chunk-R6K76UTR.js.map +0 -1
  276. package/dist/chunk-SJIVGCNM.mjs.map +0 -1
  277. package/dist/chunk-TGBXBUWM.mjs.map +0 -1
  278. /package/dist/{BlockNoteEditor-436ZHDY3.mjs.map → BlockNoteEditor-HFX7Z5BQ.mjs.map} +0 -0
  279. /package/dist/{JsonApiRequest-HFWXMKMA.mjs.map → JsonApiRequest-6IPS3DZJ.mjs.map} +0 -0
@@ -1,7 +1,9 @@
1
1
  import {
2
2
  getApiUrl,
3
3
  getAppUrl,
4
+ getI18nLink,
4
5
  getRoleId,
6
+ getStripePublishableKey,
5
7
  getTrackablePages,
6
8
  isDiscordConfigured,
7
9
  isInternalAuthConfigured,
@@ -9,7 +11,7 @@ import {
9
11
  useI18nLocale,
10
12
  useI18nRouter,
11
13
  useI18nTranslations
12
- } from "./chunk-SJIVGCNM.mjs";
14
+ } from "./chunk-POKIJ56Q.mjs";
13
15
  import {
14
16
  AuthService,
15
17
  ClientAbstractService,
@@ -22,6 +24,12 @@ import {
22
24
  RehydrationFactory,
23
25
  RoleService,
24
26
  S3Service,
27
+ StripeCustomerService,
28
+ StripeInvoiceService,
29
+ StripePriceService,
30
+ StripeProductService,
31
+ StripeSubscriptionService,
32
+ StripeUsageService,
25
33
  UserService,
26
34
  checkPermissions,
27
35
  cn,
@@ -30,7 +38,7 @@ import {
30
38
  rehydrate,
31
39
  useComposedRefs,
32
40
  useIsMobile
33
- } from "./chunk-A333VMBO.mjs";
41
+ } from "./chunk-BCQSE3EU.mjs";
34
42
  import {
35
43
  __name
36
44
  } from "./chunk-PAWJFY3S.mjs";
@@ -4792,11 +4800,11 @@ function KanbanOverlay(props) {
4792
4800
  __name(KanbanOverlay, "KanbanOverlay");
4793
4801
 
4794
4802
  // src/shadcnui/custom/link.tsx
4795
- import NextLink from "next/link";
4796
4803
  import * as React33 from "react";
4797
4804
  import { jsx as jsx46 } from "react/jsx-runtime";
4798
- var Link2 = React33.forwardRef(({ className, ...props }, ref) => {
4799
- return /* @__PURE__ */ jsx46(NextLink, { ref, className: cn(`font-medium`, className), ...props });
4805
+ var Link2 = React33.forwardRef(({ className, href, children, ...props }, ref) => {
4806
+ const NextIntlLink = getI18nLink();
4807
+ return /* @__PURE__ */ jsx46(NextIntlLink, { prefetch: false, ref, href, className: cn(`font-medium`, className), ...props, children });
4800
4808
  });
4801
4809
  Link2.displayName = "Link";
4802
4810
 
@@ -5175,7 +5183,7 @@ function UserEditorInternal({ user, propagateChanges, adminCreated, trigger, onR
5175
5183
  useEffect9(() => {
5176
5184
  if (!companyFromContext && userCompany) setCompany(userCompany);
5177
5185
  }, [company]);
5178
- const formSchema = z.object({
5186
+ const formSchema2 = z.object({
5179
5187
  id: z.uuidv4(),
5180
5188
  name: z.string().min(1, { message: t(`foundations.user.fields.name.error`) }),
5181
5189
  email: z.string().min(1, { message: t(`generic.fields.email.error`) }),
@@ -5188,7 +5196,7 @@ function UserEditorInternal({ user, propagateChanges, adminCreated, trigger, onR
5188
5196
  avatar: z.string().optional()
5189
5197
  });
5190
5198
  const form = useForm({
5191
- resolver: zodResolver(formSchema),
5199
+ resolver: zodResolver(formSchema2),
5192
5200
  defaultValues: {
5193
5201
  id: user?.id || v4(),
5194
5202
  name: user?.name || "",
@@ -6331,12 +6339,12 @@ function CompanyConfigurationEditorInternal({ company }) {
6331
6339
  setOpen(false);
6332
6340
  form.reset();
6333
6341
  }, "close");
6334
- const formSchema = z2.object({
6342
+ const formSchema2 = z2.object({
6335
6343
  isManagedKnowledge: z2.boolean().optional(),
6336
6344
  allowPublicBot: z2.boolean().optional()
6337
6345
  });
6338
6346
  const form = useForm2({
6339
- resolver: zodResolver2(formSchema),
6347
+ resolver: zodResolver2(formSchema2),
6340
6348
  defaultValues,
6341
6349
  shouldUnregister: false
6342
6350
  });
@@ -6510,7 +6518,7 @@ function CompanyEditorInternal({ company, propagateChanges, onRevalidate }) {
6510
6518
  const [contentType, setContentType] = useState16(null);
6511
6519
  const t = useTranslations22();
6512
6520
  const generateUrl = usePageUrlGenerator();
6513
- const formSchema = z3.object({
6521
+ const formSchema2 = z3.object({
6514
6522
  id: z3.uuidv4(),
6515
6523
  name: z3.string().min(1, {
6516
6524
  message: t(`foundations.company.fields.name.error`)
@@ -6520,7 +6528,7 @@ function CompanyEditorInternal({ company, propagateChanges, onRevalidate }) {
6520
6528
  logo: z3.string().optional()
6521
6529
  });
6522
6530
  const form = useForm3({
6523
- resolver: zodResolver3(formSchema),
6531
+ resolver: zodResolver3(formSchema2),
6524
6532
  defaultValues: {
6525
6533
  id: company?.id || v42(),
6526
6534
  name: company?.name || "",
@@ -6574,7 +6582,7 @@ function CompanyEditorInternal({ company, propagateChanges, onRevalidate }) {
6574
6582
  if (hasRole(getRoleId().Administrator)) {
6575
6583
  setFeatures(allfeatures);
6576
6584
  } else {
6577
- setFeatures(allfeatures.filter((feature) => feature.isProduction));
6585
+ setFeatures(allfeatures.filter((feature) => feature.isCore));
6578
6586
  }
6579
6587
  }
6580
6588
  __name(fetchFeatures, "fetchFeatures");
@@ -6735,7 +6743,6 @@ var CompanyProvider = /* @__PURE__ */ __name(({ children, dehydratedCompany }) =
6735
6743
  if (company && hasRole(getRoleId().Administrator) && hasPermissionToModule({ module: Modules.Company, action: "delete" /* Delete */ }))
6736
6744
  functions.push(/* @__PURE__ */ jsx79(CompanyDeleter, { company }, "companyDeleter"));
6737
6745
  if (hasRole(getRoleId().Administrator) || hasPermissionToModule({ module: Modules.Company, action: "update" /* Update */ })) {
6738
- if (company) functions.push(/* @__PURE__ */ jsx79(CompanyConfigurationEditor, { company }, "companyConfigurationEditor"));
6739
6746
  functions.push(/* @__PURE__ */ jsx79(CompanyEditor, { company, propagateChanges: setCompany }, "companyEditor"));
6740
6747
  }
6741
6748
  if (functions.length > 0) response.functions = functions;
@@ -7664,7 +7671,7 @@ __name(AllowedUsersDetails, "AllowedUsersDetails");
7664
7671
  import dynamic from "next/dynamic";
7665
7672
  import React38 from "react";
7666
7673
  import { jsx as jsx97 } from "react/jsx-runtime";
7667
- var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-436ZHDY3.mjs"), {
7674
+ var BlockNoteEditor = dynamic(() => import("./BlockNoteEditor-HFX7Z5BQ.mjs"), {
7668
7675
  ssr: false
7669
7676
  });
7670
7677
  var BlockNoteEditorContainer = React38.memo(/* @__PURE__ */ __name(function EditorContainer(props) {
@@ -7951,7 +7958,7 @@ var DatePickerPopover = /* @__PURE__ */ __name(({
7951
7958
  () => new Intl.DateTimeFormat(locale, { day: "2-digit", month: "2-digit", year: "numeric" }),
7952
7959
  [locale]
7953
7960
  );
7954
- const formatDate = /* @__PURE__ */ __name((date) => dateFormatter.format(date), "formatDate");
7961
+ const formatDate5 = /* @__PURE__ */ __name((date) => dateFormatter.format(date), "formatDate");
7955
7962
  const datePlaceholder = useMemo7(() => {
7956
7963
  const parts = dateFormatter.formatToParts(new Date(2e3, 0, 1));
7957
7964
  return parts.map((part) => {
@@ -7970,7 +7977,7 @@ var DatePickerPopover = /* @__PURE__ */ __name(({
7970
7977
  return part.value;
7971
7978
  }).join("");
7972
7979
  }, [dateFormatter]);
7973
- const [inputValue, setInputValue] = useState28(() => value ? formatDate(value) : "");
7980
+ const [inputValue, setInputValue] = useState28(() => value ? formatDate5(value) : "");
7974
7981
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
7975
7982
  const yearOptions = Array.from({ length: currentYear - 1900 + 11 }, (_, i) => 1900 + i);
7976
7983
  const monthNames = useMemo7(() => {
@@ -7993,7 +8000,7 @@ var DatePickerPopover = /* @__PURE__ */ __name(({
7993
8000
  const handleCalendarSelect = /* @__PURE__ */ __name((selectedDate) => {
7994
8001
  onSelect(selectedDate);
7995
8002
  if (selectedDate) {
7996
- setInputValue(formatDate(selectedDate));
8003
+ setInputValue(formatDate5(selectedDate));
7997
8004
  setDisplayMonth(selectedDate);
7998
8005
  } else {
7999
8006
  setInputValue("");
@@ -8528,7 +8535,7 @@ function FormDate({
8528
8535
  () => new Intl.DateTimeFormat(locale, { day: "2-digit", month: "2-digit", year: "numeric" }),
8529
8536
  [locale]
8530
8537
  );
8531
- const formatDate = /* @__PURE__ */ __name((date) => dateFormatter.format(date), "formatDate");
8538
+ const formatDate5 = /* @__PURE__ */ __name((date) => dateFormatter.format(date), "formatDate");
8532
8539
  const datePlaceholder = useMemo8(() => {
8533
8540
  const parts = dateFormatter.formatToParts(new Date(2e3, 0, 1));
8534
8541
  return parts.map((part) => {
@@ -8549,7 +8556,7 @@ function FormDate({
8549
8556
  }, [dateFormatter]);
8550
8557
  const [inputValue, setInputValue] = useState31(() => {
8551
8558
  const currentValue = form.getValues(id);
8552
- return currentValue ? formatDate(currentValue) : "";
8559
+ return currentValue ? formatDate5(currentValue) : "";
8553
8560
  });
8554
8561
  const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
8555
8562
  const yearOptions = Array.from({ length: currentYear - 1900 + 1 }, (_, i) => 1900 + i);
@@ -8575,7 +8582,7 @@ function FormDate({
8575
8582
  const handleCalendarSelect = /* @__PURE__ */ __name((selectedDate, field) => {
8576
8583
  field.onChange(selectedDate);
8577
8584
  if (selectedDate) {
8578
- setInputValue(formatDate(selectedDate));
8585
+ setInputValue(formatDate5(selectedDate));
8579
8586
  setDisplayMonth(selectedDate);
8580
8587
  } else {
8581
8588
  setInputValue("");
@@ -8712,7 +8719,7 @@ function FormDateTime({
8712
8719
  }),
8713
8720
  [locale]
8714
8721
  );
8715
- const formatDateTime = /* @__PURE__ */ __name((date) => dateTimeFormatter.format(date), "formatDateTime");
8722
+ const formatDateTime2 = /* @__PURE__ */ __name((date) => dateTimeFormatter.format(date), "formatDateTime");
8716
8723
  const [selectedHours, setSelectedHours] = useState32((/* @__PURE__ */ new Date()).getHours());
8717
8724
  const [selectedMinutes, setSelectedMinutes] = useState32(roundToNearestFiveMinutes((/* @__PURE__ */ new Date()).getMinutes()));
8718
8725
  const hoursOptions = Array.from({ length: 24 }, (_, i) => {
@@ -8758,7 +8765,7 @@ function FormDateTime({
8758
8765
  variant: "outline",
8759
8766
  className: cn("w-full pl-3 text-left font-normal", !field.value && "text-muted-foreground"),
8760
8767
  children: [
8761
- field.value ? formatDateTime(field.value) : /* @__PURE__ */ jsx110("span", { children: t(`generic.pick_date_time`) }),
8768
+ field.value ? formatDateTime2(field.value) : /* @__PURE__ */ jsx110("span", { children: t(`generic.pick_date_time`) }),
8762
8769
  /* @__PURE__ */ jsx110(CalendarIcon4, { className: "ml-auto h-4 w-4 opacity-50" })
8763
8770
  ]
8764
8771
  }
@@ -9371,118 +9378,35 @@ var dropzone = {
9371
9378
 
9372
9379
  // src/features/feature/components/forms/FormFeatures.tsx
9373
9380
  import { jsx as jsx120, jsxs as jsxs72 } from "react/jsx-runtime";
9374
- function FormFeatures({
9375
- form,
9376
- name,
9377
- features,
9378
- featureField = "featureIds",
9379
- moduleField = "moduleIds"
9380
- }) {
9381
+ function FormFeatures({ form, name, features, featureField = "featureIds" }) {
9381
9382
  const selectedFeatures = form.watch(featureField);
9382
- const selectedModules = form.watch(moduleField);
9383
9383
  const toggleFeature = /* @__PURE__ */ __name((feature, checked) => {
9384
9384
  let newFeatureIds = [...selectedFeatures];
9385
- let newModuleIds = [...selectedModules];
9386
9385
  if (checked) {
9387
9386
  if (!newFeatureIds.includes(feature.id)) {
9388
9387
  newFeatureIds.push(feature.id);
9389
9388
  }
9390
- feature.modules.forEach((module) => {
9391
- if (!newModuleIds.includes(module.id)) {
9392
- newModuleIds.push(module.id);
9393
- }
9394
- });
9395
9389
  } else {
9396
9390
  newFeatureIds = newFeatureIds.filter((id) => id !== feature.id);
9397
- feature.modules.forEach((module) => {
9398
- newModuleIds = newModuleIds.filter((id) => id !== module.id);
9399
- });
9400
9391
  }
9401
9392
  form.setValue(featureField, newFeatureIds);
9402
- form.setValue(moduleField, newModuleIds);
9403
9393
  }, "toggleFeature");
9404
- const toggleModule = /* @__PURE__ */ __name((feature, module, checked) => {
9405
- const modulesForFeature = feature.modules.map((m) => m.id);
9406
- let newModuleIds = [...selectedModules];
9407
- if (checked) {
9408
- if (!selectedFeatures.includes(feature.id)) {
9409
- newModuleIds = newModuleIds.filter((id) => !modulesForFeature.includes(id));
9410
- newModuleIds.push(module.id);
9411
- form.setValue(featureField, [...selectedFeatures, feature.id]);
9412
- } else {
9413
- if (!newModuleIds.includes(module.id)) {
9414
- newModuleIds.push(module.id);
9415
- }
9416
- }
9417
- } else {
9418
- newModuleIds = newModuleIds.filter((id) => id !== module.id);
9419
- const remaining = feature.modules.filter((m) => newModuleIds.includes(m.id));
9420
- if (remaining.length === 0) {
9421
- form.setValue(
9422
- featureField,
9423
- selectedFeatures.filter((id) => id !== feature.id)
9424
- );
9425
- }
9426
- }
9427
- form.setValue(moduleField, newModuleIds);
9428
- }, "toggleModule");
9429
- const isFeatureChecked = /* @__PURE__ */ __name((feature) => selectedFeatures.includes(feature.id) || feature.modules.every((module) => selectedModules.includes(module.id)), "isFeatureChecked");
9394
+ const isFeatureChecked = /* @__PURE__ */ __name((feature) => selectedFeatures.includes(feature.id), "isFeatureChecked");
9430
9395
  return /* @__PURE__ */ jsxs72("div", { className: "flex w-full flex-col", children: [
9431
- name && /* @__PURE__ */ jsx120("h2", { className: "mb-5 font-semibold", children: name }),
9432
- features.map((feature) => /* @__PURE__ */ jsx120(
9433
- Accordion,
9434
- {
9435
- type: "single",
9436
- collapsible: true,
9437
- className: `w-full p-0`,
9438
- children: /* @__PURE__ */ jsxs72(AccordionItem, { value: feature.id, className: "p-0", children: [
9439
- /* @__PURE__ */ jsxs72(
9440
- "div",
9441
- {
9442
- className: `flex items-center justify-between p-0 ${feature.modules.filter((module) => !module.isCore).length === 0 ? "py-4" : ""}`,
9443
- children: [
9444
- /* @__PURE__ */ jsxs72("div", { className: "flex items-center", onClick: (e) => e.stopPropagation(), children: [
9445
- /* @__PURE__ */ jsx120(
9446
- Checkbox,
9447
- {
9448
- id: feature.id,
9449
- checked: isFeatureChecked(feature),
9450
- onCheckedChange: (val) => {
9451
- toggleFeature(feature, val === true);
9452
- }
9453
- }
9454
- ),
9455
- /* @__PURE__ */ jsx120(FormLabel, { htmlFor: feature.id, className: "ml-3 cursor-pointer font-normal", children: feature.name })
9456
- ] }),
9457
- feature.modules.filter((module) => !module.isCore).length > 0 && /* @__PURE__ */ jsx120(AccordionTrigger, { asChild: true, children: /* @__PURE__ */ jsx120("div", { className: "w-full" }) })
9458
- ]
9459
- }
9460
- ),
9461
- feature.modules.filter((module) => !module.isCore).length > 0 && /* @__PURE__ */ jsx120(AccordionContent, { className: "pl-6", children: feature.modules.filter((module) => !module.isCore).sort((a, b) => a.name.localeCompare(b.name)).map((module) => /* @__PURE__ */ jsxs72(
9462
- "div",
9463
- {
9464
- className: "flex items-center border-t py-2",
9465
- onClick: (e) => e.stopPropagation(),
9466
- children: [
9467
- /* @__PURE__ */ jsx120(
9468
- Checkbox,
9469
- {
9470
- id: module.id,
9471
- checked: selectedModules.includes(module.id),
9472
- onCheckedChange: (val) => {
9473
- toggleModule(feature, module, val === true);
9474
- }
9475
- }
9476
- ),
9477
- /* @__PURE__ */ jsx120(FormLabel, { htmlFor: module.id, className: "ml-3 cursor-pointer font-normal", children: module.name })
9478
- ]
9479
- },
9480
- module.id
9481
- )) })
9482
- ] })
9483
- },
9484
- feature.id
9485
- )),
9396
+ name && /* @__PURE__ */ jsx120("h2", { className: "mb-4 border-b text-lg font-semibold", children: name }),
9397
+ /* @__PURE__ */ jsx120(ScrollArea, { className: "h-[40vh]", children: /* @__PURE__ */ jsx120("div", { className: "flex flex-col gap-y-2 pr-4", children: features.filter((feature) => !feature.isCore).map((feature) => /* @__PURE__ */ jsxs72("div", { className: "flex items-center", children: [
9398
+ /* @__PURE__ */ jsx120(
9399
+ Checkbox,
9400
+ {
9401
+ id: feature.id,
9402
+ checked: isFeatureChecked(feature),
9403
+ onCheckedChange: (val) => {
9404
+ toggleFeature(feature, val === true);
9405
+ }
9406
+ }
9407
+ ),
9408
+ /* @__PURE__ */ jsx120(FormLabel, { htmlFor: feature.id, className: "ml-3 cursor-pointer font-normal", children: feature.name })
9409
+ ] }, feature.id)) }) }),
9486
9410
  /* @__PURE__ */ jsx120(FormMessage, {})
9487
9411
  ] });
9488
9412
  }
@@ -9688,7 +9612,7 @@ function useJsonApiGet(params) {
9688
9612
  setLoading(true);
9689
9613
  setError(null);
9690
9614
  try {
9691
- const { JsonApiGet } = await import("./JsonApiRequest-HFWXMKMA.mjs");
9615
+ const { JsonApiGet } = await import("./JsonApiRequest-6IPS3DZJ.mjs");
9692
9616
  const language = navigator.language.split("-")[0] || "en";
9693
9617
  const apiResponse = await JsonApiGet({
9694
9618
  classKey: params.classKey,
@@ -9793,7 +9717,7 @@ function useJsonApiMutation(config) {
9793
9717
  setLoading(true);
9794
9718
  setError(null);
9795
9719
  try {
9796
- const { JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } = await import("./JsonApiRequest-HFWXMKMA.mjs");
9720
+ const { JsonApiPost, JsonApiPut, JsonApiPatch, JsonApiDelete } = await import("./JsonApiRequest-6IPS3DZJ.mjs");
9797
9721
  const language = navigator.language.split("-")[0] || "en";
9798
9722
  let apiResponse;
9799
9723
  switch (config.method) {
@@ -10455,7 +10379,7 @@ function Register() {
10455
10379
  const t = useTranslations46();
10456
10380
  const { setComponentType } = useAuthContext();
10457
10381
  const [showConfirmation, setShowConfirmation] = useState42(false);
10458
- const formSchema = z5.object({
10382
+ const formSchema2 = z5.object({
10459
10383
  company: z5.string().min(1, {
10460
10384
  message: t(`generic.errors.missing_company_name`)
10461
10385
  }),
@@ -10470,7 +10394,7 @@ function Register() {
10470
10394
  })
10471
10395
  });
10472
10396
  const form = useForm5({
10473
- resolver: zodResolver5(formSchema),
10397
+ resolver: zodResolver5(formSchema2),
10474
10398
  defaultValues: {
10475
10399
  company: "",
10476
10400
  name: "",
@@ -10701,7 +10625,7 @@ function AcceptInvitation() {
10701
10625
  setError(t(`foundations.auth.errors.invalid_invitation_code`));
10702
10626
  }
10703
10627
  }, []);
10704
- const formSchema = z6.object({
10628
+ const formSchema2 = z6.object({
10705
10629
  password: z6.string().min(1, {
10706
10630
  message: t(`foundations.user.fields.password.error`)
10707
10631
  }),
@@ -10713,7 +10637,7 @@ function AcceptInvitation() {
10713
10637
  path: ["passwordRetype"]
10714
10638
  });
10715
10639
  const form = useForm6({
10716
- resolver: zodResolver6(formSchema),
10640
+ resolver: zodResolver6(formSchema2),
10717
10641
  defaultValues: {
10718
10642
  password: "",
10719
10643
  passwordRetype: ""
@@ -10860,13 +10784,13 @@ function ForgotPassword() {
10860
10784
  const t = useTranslations50();
10861
10785
  const { setComponentType } = useAuthContext();
10862
10786
  const [showConfirmation, setShowConfirmation] = useState47(false);
10863
- const formSchema = z7.object({
10787
+ const formSchema2 = z7.object({
10864
10788
  email: z7.string().email({
10865
10789
  message: t(`generic.errors.invalid_email`)
10866
10790
  })
10867
10791
  });
10868
10792
  const form = useForm7({
10869
- resolver: zodResolver7(formSchema),
10793
+ resolver: zodResolver7(formSchema2),
10870
10794
  defaultValues: {
10871
10795
  email: ""
10872
10796
  }
@@ -10932,14 +10856,14 @@ function Login() {
10932
10856
  const { setComponentType } = useAuthContext();
10933
10857
  const generateUrl = usePageUrlGenerator();
10934
10858
  const router = useI18nRouter();
10935
- const formSchema = z8.object({
10859
+ const formSchema2 = z8.object({
10936
10860
  email: z8.string().email({
10937
10861
  message: t(`generic.errors.invalid_email`)
10938
10862
  }),
10939
10863
  password: z8.string().min(3, { message: t(`foundations.auth.errors.password_too_short`) })
10940
10864
  });
10941
10865
  const form = useForm8({
10942
- resolver: zodResolver8(formSchema),
10866
+ resolver: zodResolver8(formSchema2),
10943
10867
  defaultValues: {
10944
10868
  email: "",
10945
10869
  password: ""
@@ -11099,7 +11023,7 @@ function ResetPassword() {
11099
11023
  setError(t(`foundations.auth.errors.invalid_password_reset_code`));
11100
11024
  }
11101
11025
  }, []);
11102
- const formSchema = z9.object({
11026
+ const formSchema2 = z9.object({
11103
11027
  password: z9.string().min(1, {
11104
11028
  message: t(`foundations.user.fields.password.error`)
11105
11029
  }),
@@ -11111,7 +11035,7 @@ function ResetPassword() {
11111
11035
  path: ["passwordRetype"]
11112
11036
  });
11113
11037
  const form = useForm9({
11114
- resolver: zodResolver9(formSchema),
11038
+ resolver: zodResolver9(formSchema2),
11115
11039
  defaultValues: {
11116
11040
  password: "",
11117
11041
  passwordRetype: ""
@@ -11154,217 +11078,3580 @@ function ResetPassword() {
11154
11078
  }
11155
11079
  __name(ResetPassword, "ResetPassword");
11156
11080
 
11157
- // src/features/content/components/lists/ContentsList.tsx
11158
- import { useTranslations as useTranslations53 } from "next-intl";
11081
+ // src/features/billing/components/cards/SubscriptionSummaryCard.tsx
11082
+ import { ChevronRight, CreditCard } from "lucide-react";
11159
11083
  import { jsx as jsx144, jsxs as jsxs86 } from "react/jsx-runtime";
11160
- function ContentsList({ contentList }) {
11161
- const t = useTranslations53();
11162
- return /* @__PURE__ */ jsxs86("div", { className: "flex min-h-0 w-full flex-col overflow-y-auto", children: [
11163
- /* @__PURE__ */ jsx144("h2", { className: "text-xl font-semibold", children: t(`foundations.content.news`) }),
11164
- /* @__PURE__ */ jsx144("div", { className: "flex flex-col", children: contentList.map((content) => /* @__PURE__ */ jsx144(ContentsListElement, { content }, content.id)) })
11165
- ] });
11166
- }
11167
- __name(ContentsList, "ContentsList");
11168
- function ContentsListElement({ content }) {
11169
- const generateUrl = usePageUrlGenerator();
11170
- const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : void 0;
11171
- const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : "#";
11172
- return /* @__PURE__ */ jsx144("div", { className: "hover:bg-muted flex w-full flex-col gap-y-2 border-b p-2 py-4", children: /* @__PURE__ */ jsxs86("div", { className: "flex w-full justify-between gap-x-2", children: [
11173
- /* @__PURE__ */ jsxs86(HoverCard, { children: [
11174
- /* @__PURE__ */ jsx144(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs86(Link2, { href: link, className: "flex w-full items-center justify-start gap-2 font-semibold", children: [
11175
- contentModule && getIconByModule({ module: contentModule, className: "h-4 w-4" }),
11176
- content.name
11177
- ] }) }),
11178
- /* @__PURE__ */ jsxs86(HoverCardContent, { className: "flex max-h-96 w-96 flex-col gap-y-4 overflow-y-auto", children: [
11179
- /* @__PURE__ */ jsx144(Link2, { href: link, className: "font-semibold", children: content.name }),
11180
- /* @__PURE__ */ jsx144("div", { className: "text-xs", children: content.abstract })
11181
- ] })
11182
- ] }),
11183
- /* @__PURE__ */ jsx144(ContributorsList, { content })
11184
- ] }) });
11185
- }
11186
- __name(ContentsListElement, "ContentsListElement");
11187
-
11188
- // src/features/content/components/lists/ContentsListById.tsx
11189
- import { useTranslations as useTranslations54 } from "next-intl";
11190
- import { jsx as jsx145 } from "react/jsx-runtime";
11191
- function ContentsListById({ contentIds }) {
11192
- const t = useTranslations54();
11193
- const data = useDataListRetriever({
11194
- module: Modules.Content,
11195
- retriever: /* @__PURE__ */ __name((params) => ContentService.findMany(params), "retriever"),
11196
- retrieverParams: { contentIds }
11084
+ function getStatusBadgeVariant(status) {
11085
+ switch (status) {
11086
+ case "active" /* ACTIVE */:
11087
+ return "default";
11088
+ case "trialing" /* TRIALING */:
11089
+ return "secondary";
11090
+ case "past_due" /* PAST_DUE */:
11091
+ case "unpaid" /* UNPAID */:
11092
+ case "canceled" /* CANCELED */:
11093
+ return "destructive";
11094
+ default:
11095
+ return "outline";
11096
+ }
11097
+ }
11098
+ __name(getStatusBadgeVariant, "getStatusBadgeVariant");
11099
+ function formatDate(date) {
11100
+ return new Date(date).toLocaleDateString(void 0, {
11101
+ year: "numeric",
11102
+ month: "short",
11103
+ day: "numeric"
11197
11104
  });
11198
- return /* @__PURE__ */ jsx145(
11199
- ContentListTable,
11200
- {
11201
- data,
11202
- fields: ["name" /* name */, "authors" /* authors */, "updatedAt" /* updatedAt */],
11203
- tableGeneratorType: Modules.Content,
11204
- title: t(`generic.relevant`)
11205
- }
11206
- );
11207
11105
  }
11208
- __name(ContentsListById, "ContentsListById");
11209
-
11210
- // src/features/content/components/lists/RelevantContentsList.tsx
11211
- import { useTranslations as useTranslations55 } from "next-intl";
11212
- import { jsx as jsx146 } from "react/jsx-runtime";
11213
- function RelevantContentsList({ id }) {
11214
- const t = useTranslations55();
11215
- const data = useDataListRetriever({
11216
- module: Modules.Content,
11217
- retriever: /* @__PURE__ */ __name((params) => ContentService.findRelevant(params), "retriever"),
11218
- retrieverParams: { id }
11219
- });
11220
- return /* @__PURE__ */ jsx146(
11221
- ContentListTable,
11222
- {
11223
- data,
11224
- fields: ["name" /* name */, "authors" /* authors */, "relevance" /* relevance */, "updatedAt" /* updatedAt */],
11225
- tableGeneratorType: Modules.Content,
11226
- title: t(`generic.relevant`)
11227
- }
11106
+ __name(formatDate, "formatDate");
11107
+ function formatPrice(amount, currency) {
11108
+ if (amount === void 0) return "N/A";
11109
+ const currencyCode = currency?.toUpperCase() || "USD";
11110
+ return new Intl.NumberFormat(void 0, {
11111
+ style: "currency",
11112
+ currency: currencyCode
11113
+ }).format(amount / 100);
11114
+ }
11115
+ __name(formatPrice, "formatPrice");
11116
+ function formatPlanName(subscription) {
11117
+ const productName = subscription.price?.product?.name || "";
11118
+ const nickname = subscription.price?.nickname || "";
11119
+ if (productName && nickname) {
11120
+ return `${productName} - ${nickname}`;
11121
+ }
11122
+ return productName || nickname || "Subscription";
11123
+ }
11124
+ __name(formatPlanName, "formatPlanName");
11125
+ function SubscriptionSummaryCard({
11126
+ subscriptions,
11127
+ loading,
11128
+ error,
11129
+ onManageClick
11130
+ }) {
11131
+ if (loading) {
11132
+ return /* @__PURE__ */ jsxs86(Card, { children: [
11133
+ /* @__PURE__ */ jsxs86(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11134
+ /* @__PURE__ */ jsx144(CardTitle, { className: "text-sm font-medium", children: "Subscriptions" }),
11135
+ /* @__PURE__ */ jsx144(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
11136
+ ] }),
11137
+ /* @__PURE__ */ jsxs86(CardContent, { children: [
11138
+ /* @__PURE__ */ jsx144(Skeleton, { className: "h-6 w-32 mb-2" }),
11139
+ /* @__PURE__ */ jsx144(Skeleton, { className: "h-4 w-24 mb-1" }),
11140
+ /* @__PURE__ */ jsx144(Skeleton, { className: "h-4 w-40" })
11141
+ ] })
11142
+ ] });
11143
+ }
11144
+ if (error) {
11145
+ return /* @__PURE__ */ jsxs86(Card, { children: [
11146
+ /* @__PURE__ */ jsxs86(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11147
+ /* @__PURE__ */ jsx144(CardTitle, { className: "text-sm font-medium", children: "Subscriptions" }),
11148
+ /* @__PURE__ */ jsx144(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
11149
+ ] }),
11150
+ /* @__PURE__ */ jsx144(CardContent, { children: /* @__PURE__ */ jsx144("p", { className: "text-sm text-destructive", children: error }) })
11151
+ ] });
11152
+ }
11153
+ const activeSubscriptions = subscriptions.filter(
11154
+ (sub) => sub.status === "active" /* ACTIVE */ || sub.status === "trialing" /* TRIALING */
11228
11155
  );
11156
+ const primarySubscription = activeSubscriptions[0];
11157
+ return /* @__PURE__ */ jsxs86(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onManageClick, children: [
11158
+ /* @__PURE__ */ jsxs86(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11159
+ /* @__PURE__ */ jsx144(CardTitle, { className: "text-sm font-medium", children: "Subscriptions" }),
11160
+ /* @__PURE__ */ jsx144(CreditCard, { className: "h-4 w-4 text-muted-foreground" })
11161
+ ] }),
11162
+ /* @__PURE__ */ jsx144(CardContent, { children: subscriptions.length === 0 ? /* @__PURE__ */ jsxs86("div", { className: "space-y-2", children: [
11163
+ /* @__PURE__ */ jsx144("p", { className: "text-xl font-bold text-muted-foreground", children: "No active plan" }),
11164
+ /* @__PURE__ */ jsx144("p", { className: "text-xs text-muted-foreground", children: "Subscribe to get started" }),
11165
+ /* @__PURE__ */ jsxs86(
11166
+ Button,
11167
+ {
11168
+ variant: "outline",
11169
+ size: "sm",
11170
+ className: "mt-2",
11171
+ onClick: (e) => {
11172
+ e.stopPropagation();
11173
+ onManageClick();
11174
+ },
11175
+ children: [
11176
+ "View Plans",
11177
+ /* @__PURE__ */ jsx144(ChevronRight, { className: "h-4 w-4 ml-1" })
11178
+ ]
11179
+ }
11180
+ )
11181
+ ] }) : primarySubscription ? /* @__PURE__ */ jsxs86("div", { className: "space-y-2", children: [
11182
+ /* @__PURE__ */ jsxs86("div", { className: "flex items-center gap-2", children: [
11183
+ /* @__PURE__ */ jsx144("p", { className: "text-xl font-bold", children: formatPlanName(primarySubscription) }),
11184
+ /* @__PURE__ */ jsx144(Badge, { variant: primarySubscription.cancelAtPeriodEnd ? "secondary" : getStatusBadgeVariant(primarySubscription.status), children: primarySubscription.cancelAtPeriodEnd ? "Canceling" : primarySubscription.status })
11185
+ ] }),
11186
+ /* @__PURE__ */ jsxs86("p", { className: "text-sm text-muted-foreground", children: [
11187
+ formatPrice(primarySubscription.price?.unitAmount, primarySubscription.price?.currency),
11188
+ primarySubscription.price?.recurring && /* @__PURE__ */ jsxs86("span", { children: [
11189
+ "/",
11190
+ primarySubscription.price.recurring.interval
11191
+ ] })
11192
+ ] }),
11193
+ /* @__PURE__ */ jsx144("p", { className: "text-xs text-muted-foreground", children: primarySubscription.cancelAtPeriodEnd ? `Cancels on ${formatDate(primarySubscription.currentPeriodEnd)}` : `Renews on ${formatDate(primarySubscription.currentPeriodEnd)}` }),
11194
+ activeSubscriptions.length > 1 && /* @__PURE__ */ jsxs86("p", { className: "text-xs text-muted-foreground", children: [
11195
+ "+",
11196
+ activeSubscriptions.length - 1,
11197
+ " more subscription(s)"
11198
+ ] })
11199
+ ] }) : null })
11200
+ ] });
11229
11201
  }
11230
- __name(RelevantContentsList, "RelevantContentsList");
11231
-
11232
- // src/features/notification/components/common/NotificationErrorBoundary.tsx
11233
- import { Component } from "react";
11234
- import { jsx as jsx147, jsxs as jsxs87 } from "react/jsx-runtime";
11235
- var NotificationErrorBoundary = class extends Component {
11236
- static {
11237
- __name(this, "NotificationErrorBoundary");
11202
+ __name(SubscriptionSummaryCard, "SubscriptionSummaryCard");
11203
+
11204
+ // src/features/billing/components/cards/PaymentMethodSummaryCard.tsx
11205
+ import { Wallet, ChevronRight as ChevronRight2 } from "lucide-react";
11206
+ import { jsx as jsx145, jsxs as jsxs87 } from "react/jsx-runtime";
11207
+ function getCardBrandIcon(brand) {
11208
+ const brandMap = {
11209
+ visa: "Visa",
11210
+ mastercard: "Mastercard",
11211
+ amex: "Amex",
11212
+ discover: "Discover",
11213
+ diners: "Diners",
11214
+ jcb: "JCB",
11215
+ unionpay: "UnionPay"
11216
+ };
11217
+ return brandMap[brand.toLowerCase()] || brand;
11218
+ }
11219
+ __name(getCardBrandIcon, "getCardBrandIcon");
11220
+ function PaymentMethodSummaryCard({
11221
+ paymentMethods,
11222
+ defaultPaymentMethodId,
11223
+ loading,
11224
+ error,
11225
+ onManageClick
11226
+ }) {
11227
+ if (loading) {
11228
+ return /* @__PURE__ */ jsxs87(Card, { children: [
11229
+ /* @__PURE__ */ jsxs87(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11230
+ /* @__PURE__ */ jsx145(CardTitle, { className: "text-sm font-medium", children: "Payment Method" }),
11231
+ /* @__PURE__ */ jsx145(Wallet, { className: "h-4 w-4 text-muted-foreground" })
11232
+ ] }),
11233
+ /* @__PURE__ */ jsxs87(CardContent, { children: [
11234
+ /* @__PURE__ */ jsx145(Skeleton, { className: "h-6 w-32 mb-2" }),
11235
+ /* @__PURE__ */ jsx145(Skeleton, { className: "h-4 w-24" })
11236
+ ] })
11237
+ ] });
11238
11238
  }
11239
- constructor(props) {
11240
- super(props);
11241
- this.state = { hasError: false };
11239
+ if (error) {
11240
+ return /* @__PURE__ */ jsxs87(Card, { children: [
11241
+ /* @__PURE__ */ jsxs87(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11242
+ /* @__PURE__ */ jsx145(CardTitle, { className: "text-sm font-medium", children: "Payment Method" }),
11243
+ /* @__PURE__ */ jsx145(Wallet, { className: "h-4 w-4 text-muted-foreground" })
11244
+ ] }),
11245
+ /* @__PURE__ */ jsx145(CardContent, { children: /* @__PURE__ */ jsx145("p", { className: "text-sm text-destructive", children: error }) })
11246
+ ] });
11242
11247
  }
11243
- static getDerivedStateFromError(error) {
11244
- return { hasError: true, error };
11248
+ const defaultMethod = paymentMethods.find((pm) => pm.id === defaultPaymentMethodId) || paymentMethods[0];
11249
+ return /* @__PURE__ */ jsxs87(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onManageClick, children: [
11250
+ /* @__PURE__ */ jsxs87(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11251
+ /* @__PURE__ */ jsx145(CardTitle, { className: "text-sm font-medium", children: "Payment Method" }),
11252
+ /* @__PURE__ */ jsx145(Wallet, { className: "h-4 w-4 text-muted-foreground" })
11253
+ ] }),
11254
+ /* @__PURE__ */ jsx145(CardContent, { children: paymentMethods.length === 0 ? /* @__PURE__ */ jsxs87("div", { className: "space-y-2", children: [
11255
+ /* @__PURE__ */ jsx145("p", { className: "text-xl font-bold text-muted-foreground", children: "No payment method" }),
11256
+ /* @__PURE__ */ jsx145("p", { className: "text-xs text-muted-foreground", children: "Add a card to enable subscriptions" }),
11257
+ /* @__PURE__ */ jsxs87(Button, { variant: "outline", size: "sm", className: "mt-2", onClick: (e) => {
11258
+ e.stopPropagation();
11259
+ onManageClick();
11260
+ }, children: [
11261
+ "Add Card",
11262
+ /* @__PURE__ */ jsx145(ChevronRight2, { className: "h-4 w-4 ml-1" })
11263
+ ] })
11264
+ ] }) : defaultMethod?.card ? /* @__PURE__ */ jsxs87("div", { className: "space-y-2", children: [
11265
+ /* @__PURE__ */ jsxs87("p", { className: "text-xl font-bold", children: [
11266
+ getCardBrandIcon(defaultMethod.card.brand),
11267
+ " ****",
11268
+ defaultMethod.card.last4
11269
+ ] }),
11270
+ /* @__PURE__ */ jsxs87("p", { className: "text-sm text-muted-foreground", children: [
11271
+ "Expires ",
11272
+ String(defaultMethod.card.expMonth).padStart(2, "0"),
11273
+ "/",
11274
+ defaultMethod.card.expYear
11275
+ ] }),
11276
+ paymentMethods.length > 1 && /* @__PURE__ */ jsxs87("p", { className: "text-xs text-muted-foreground", children: [
11277
+ "+",
11278
+ paymentMethods.length - 1,
11279
+ " more card(s)"
11280
+ ] })
11281
+ ] }) : /* @__PURE__ */ jsxs87("div", { className: "space-y-2", children: [
11282
+ /* @__PURE__ */ jsx145("p", { className: "text-xl font-bold", children: defaultMethod?.type || "Payment Method" }),
11283
+ paymentMethods.length > 1 && /* @__PURE__ */ jsxs87("p", { className: "text-xs text-muted-foreground", children: [
11284
+ "+",
11285
+ paymentMethods.length - 1,
11286
+ " more method(s)"
11287
+ ] })
11288
+ ] }) })
11289
+ ] });
11290
+ }
11291
+ __name(PaymentMethodSummaryCard, "PaymentMethodSummaryCard");
11292
+
11293
+ // src/features/billing/components/cards/CustomerInfoCard.tsx
11294
+ import { ExternalLink, User } from "lucide-react";
11295
+ import { useState as useState49 } from "react";
11296
+ import { jsx as jsx146, jsxs as jsxs88 } from "react/jsx-runtime";
11297
+ function formatBalance(balance, currency) {
11298
+ if (balance === void 0 || balance === 0) return "$0.00";
11299
+ const currencyCode = currency?.toUpperCase() || "USD";
11300
+ const displayBalance = -balance;
11301
+ return new Intl.NumberFormat(void 0, {
11302
+ style: "currency",
11303
+ currency: currencyCode
11304
+ }).format(displayBalance / 100);
11305
+ }
11306
+ __name(formatBalance, "formatBalance");
11307
+ function CustomerInfoCard({ customer, loading, error }) {
11308
+ const [portalLoading, setPortalLoading] = useState49(false);
11309
+ const handlePortalClick = /* @__PURE__ */ __name(async (e) => {
11310
+ e.stopPropagation();
11311
+ setPortalLoading(true);
11312
+ try {
11313
+ const { url } = await StripeCustomerService.createPortalSession();
11314
+ window.open(url, "_blank");
11315
+ } catch (err) {
11316
+ console.error("[CustomerInfoCard] Failed to create portal session:", err);
11317
+ } finally {
11318
+ setPortalLoading(false);
11319
+ }
11320
+ }, "handlePortalClick");
11321
+ if (loading) {
11322
+ return /* @__PURE__ */ jsxs88(Card, { children: [
11323
+ /* @__PURE__ */ jsxs88(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11324
+ /* @__PURE__ */ jsx146(CardTitle, { className: "text-sm font-medium", children: "Billing Account" }),
11325
+ /* @__PURE__ */ jsx146(User, { className: "h-4 w-4 text-muted-foreground" })
11326
+ ] }),
11327
+ /* @__PURE__ */ jsxs88(CardContent, { children: [
11328
+ /* @__PURE__ */ jsx146(Skeleton, { className: "h-6 w-32 mb-2" }),
11329
+ /* @__PURE__ */ jsx146(Skeleton, { className: "h-4 w-48 mb-1" }),
11330
+ /* @__PURE__ */ jsx146(Skeleton, { className: "h-4 w-24" })
11331
+ ] })
11332
+ ] });
11245
11333
  }
11246
- componentDidCatch(error, errorInfo) {
11247
- console.error("\u{1F6A8} [NotificationErrorBoundary] Caught error:", error, errorInfo);
11334
+ if (error) {
11335
+ return /* @__PURE__ */ jsxs88(Card, { children: [
11336
+ /* @__PURE__ */ jsxs88(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11337
+ /* @__PURE__ */ jsx146(CardTitle, { className: "text-sm font-medium", children: "Billing Account" }),
11338
+ /* @__PURE__ */ jsx146(User, { className: "h-4 w-4 text-muted-foreground" })
11339
+ ] }),
11340
+ /* @__PURE__ */ jsx146(CardContent, { children: /* @__PURE__ */ jsx146("p", { className: "text-sm text-destructive", children: error }) })
11341
+ ] });
11248
11342
  }
11249
- render() {
11250
- if (this.state.hasError) {
11251
- return this.props.fallback || /* @__PURE__ */ jsx147("div", { className: "flex items-center justify-center p-4 text-center", children: /* @__PURE__ */ jsxs87("div", { className: "text-muted-foreground text-sm", children: [
11252
- /* @__PURE__ */ jsx147("p", { children: "Something went wrong with notifications." }),
11253
- /* @__PURE__ */ jsx147(
11254
- "button",
11255
- {
11256
- onClick: () => this.setState({ hasError: false }),
11257
- className: "text-primary mt-2 underline hover:no-underline",
11258
- children: "Try again"
11259
- }
11260
- )
11261
- ] }) });
11262
- }
11263
- return this.props.children;
11343
+ if (!customer) {
11344
+ return /* @__PURE__ */ jsxs88(Card, { children: [
11345
+ /* @__PURE__ */ jsxs88(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11346
+ /* @__PURE__ */ jsx146(CardTitle, { className: "text-sm font-medium", children: "Billing Account" }),
11347
+ /* @__PURE__ */ jsx146(User, { className: "h-4 w-4 text-muted-foreground" })
11348
+ ] }),
11349
+ /* @__PURE__ */ jsxs88(CardContent, { children: [
11350
+ /* @__PURE__ */ jsx146("p", { className: "text-xl font-bold text-muted-foreground", children: "Not set up" }),
11351
+ /* @__PURE__ */ jsx146("p", { className: "text-xs text-muted-foreground", children: "Billing account will be created when you subscribe" })
11352
+ ] })
11353
+ ] });
11264
11354
  }
11265
- };
11266
-
11267
- // src/features/notification/components/containers/NotificationsListContainer.tsx
11268
- import { useTranslations as useTranslations57 } from "next-intl";
11269
-
11270
- // src/features/notification/components/lists/NotificationsList.tsx
11271
- import { ArchiveIcon } from "lucide-react";
11272
- import { useTranslations as useTranslations56 } from "next-intl";
11273
- import { Fragment as Fragment28, jsx as jsx148, jsxs as jsxs88 } from "react/jsx-runtime";
11274
- function NotificationsList({ archived }) {
11275
- const t = useTranslations56();
11276
- const generateUrl = usePageUrlGenerator();
11277
- const data = useDataListRetriever({
11278
- retriever: /* @__PURE__ */ __name((params) => NotificationService.findMany(params), "retriever"),
11279
- retrieverParams: { isArchived: archived },
11280
- module: Modules.Notification
11355
+ return /* @__PURE__ */ jsxs88(Card, { children: [
11356
+ /* @__PURE__ */ jsxs88(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11357
+ /* @__PURE__ */ jsx146(CardTitle, { className: "text-sm font-medium", children: "Billing Account" }),
11358
+ /* @__PURE__ */ jsx146(User, { className: "h-4 w-4 text-muted-foreground" })
11359
+ ] }),
11360
+ /* @__PURE__ */ jsx146(CardContent, { children: /* @__PURE__ */ jsxs88("div", { className: "space-y-2", children: [
11361
+ customer.name && /* @__PURE__ */ jsx146("p", { className: "text-xl font-bold", children: customer.name }),
11362
+ customer.email && /* @__PURE__ */ jsx146("p", { className: "text-sm text-muted-foreground", children: customer.email }),
11363
+ customer.balance !== void 0 && customer.balance !== 0 && /* @__PURE__ */ jsxs88("p", { className: "text-sm", children: [
11364
+ /* @__PURE__ */ jsx146("span", { className: "text-muted-foreground", children: "Credit Balance: " }),
11365
+ /* @__PURE__ */ jsx146("span", { className: customer.balance < 0 ? "text-green-600" : "text-destructive", children: formatBalance(customer.balance, customer.currency) })
11366
+ ] }),
11367
+ /* @__PURE__ */ jsxs88(Button, { variant: "outline", size: "sm", className: "mt-2", onClick: handlePortalClick, disabled: portalLoading, children: [
11368
+ portalLoading ? "Loading..." : "Manage in Stripe Portal",
11369
+ /* @__PURE__ */ jsx146(ExternalLink, { className: "h-4 w-4 ml-1" })
11370
+ ] })
11371
+ ] }) })
11372
+ ] });
11373
+ }
11374
+ __name(CustomerInfoCard, "CustomerInfoCard");
11375
+
11376
+ // src/features/billing/components/cards/InvoicesSummaryCard.tsx
11377
+ import { ChevronRight as ChevronRight3, ReceiptIcon } from "lucide-react";
11378
+ import { jsx as jsx147, jsxs as jsxs89 } from "react/jsx-runtime";
11379
+ function getStatusBadgeVariant2(status) {
11380
+ switch (status) {
11381
+ case "paid" /* PAID */:
11382
+ return "default";
11383
+ case "open" /* OPEN */:
11384
+ return "secondary";
11385
+ case "uncollectible" /* UNCOLLECTIBLE */:
11386
+ case "void" /* VOID */:
11387
+ return "destructive";
11388
+ default:
11389
+ return "outline";
11390
+ }
11391
+ }
11392
+ __name(getStatusBadgeVariant2, "getStatusBadgeVariant");
11393
+ function formatDate2(date) {
11394
+ return new Date(date).toLocaleDateString(void 0, {
11395
+ year: "numeric",
11396
+ month: "short",
11397
+ day: "numeric"
11281
11398
  });
11282
- const archiveNotification = /* @__PURE__ */ __name(async (notification) => {
11283
- await NotificationService.archive({ id: notification.id });
11284
- data.removeElement(notification);
11285
- }, "archiveNotification");
11286
- const LoadingSkeleton = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx148("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx148(Card, { children: /* @__PURE__ */ jsx148(CardContent, { className: "p-2", children: /* @__PURE__ */ jsxs88("div", { className: "flex w-full flex-row items-center", children: [
11287
- /* @__PURE__ */ jsx148(Skeleton, { className: "mr-4 h-8 w-8 rounded-full" }),
11288
- /* @__PURE__ */ jsxs88("div", { className: "flex-1 space-y-2", children: [
11289
- /* @__PURE__ */ jsx148(Skeleton, { className: "h-4 w-3/4" }),
11290
- /* @__PURE__ */ jsx148(Skeleton, { className: "h-3 w-1/2" })
11399
+ }
11400
+ __name(formatDate2, "formatDate");
11401
+ function formatAmount(amount, currency) {
11402
+ const currencyCode = currency?.toUpperCase() || "USD";
11403
+ return new Intl.NumberFormat(void 0, {
11404
+ style: "currency",
11405
+ currency: currencyCode
11406
+ }).format(amount / 100);
11407
+ }
11408
+ __name(formatAmount, "formatAmount");
11409
+ function InvoicesSummaryCard({ invoices, loading, error, onViewAllClick }) {
11410
+ if (loading) {
11411
+ return /* @__PURE__ */ jsxs89(Card, { children: [
11412
+ /* @__PURE__ */ jsxs89(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11413
+ /* @__PURE__ */ jsx147(CardTitle, { className: "text-sm font-medium", children: "Recent Invoices" }),
11414
+ /* @__PURE__ */ jsx147(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
11415
+ ] }),
11416
+ /* @__PURE__ */ jsxs89(CardContent, { children: [
11417
+ /* @__PURE__ */ jsx147(Skeleton, { className: "h-6 w-24 mb-2" }),
11418
+ /* @__PURE__ */ jsx147(Skeleton, { className: "h-4 w-32 mb-1" }),
11419
+ /* @__PURE__ */ jsx147(Skeleton, { className: "h-4 w-20" })
11420
+ ] })
11421
+ ] });
11422
+ }
11423
+ if (error) {
11424
+ return /* @__PURE__ */ jsxs89(Card, { children: [
11425
+ /* @__PURE__ */ jsxs89(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11426
+ /* @__PURE__ */ jsx147(CardTitle, { className: "text-sm font-medium", children: "Recent Invoices" }),
11427
+ /* @__PURE__ */ jsx147(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
11428
+ ] }),
11429
+ /* @__PURE__ */ jsx147(CardContent, { children: /* @__PURE__ */ jsx147("p", { className: "text-sm text-destructive", children: error }) })
11430
+ ] });
11431
+ }
11432
+ const latestInvoice = invoices[0];
11433
+ const paidInvoices = invoices.filter((inv) => inv.status === "paid" /* PAID */);
11434
+ const openInvoices = invoices.filter((inv) => inv.status === "open" /* OPEN */);
11435
+ return /* @__PURE__ */ jsxs89(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onViewAllClick, children: [
11436
+ /* @__PURE__ */ jsxs89(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11437
+ /* @__PURE__ */ jsx147(CardTitle, { className: "text-sm font-medium", children: "Recent Invoices" }),
11438
+ /* @__PURE__ */ jsx147(ReceiptIcon, { className: "h-4 w-4 text-muted-foreground" })
11291
11439
  ] }),
11292
- /* @__PURE__ */ jsx148(Skeleton, { className: "h-8 w-20" })
11293
- ] }) }) }, i)) }), "LoadingSkeleton");
11294
- return /* @__PURE__ */ jsx148("div", { className: "space-y-4", children: data.isLoaded ? data.data?.map((notification) => {
11295
- const notificationData = generateNotificationData({ notification, generateUrl });
11296
- return /* @__PURE__ */ jsx148(Card, { children: /* @__PURE__ */ jsx148(CardContent, { className: "p-0", children: /* @__PURE__ */ jsxs88("div", { className: `flex w-full flex-row items-center p-2`, children: [
11297
- notificationData.actor ? /* @__PURE__ */ jsx148("div", { className: "flex w-12 max-w-12 px-2", children: /* @__PURE__ */ jsx148(Link2, { href: generateUrl({ page: Modules.User, id: notificationData.actor.id }), children: /* @__PURE__ */ jsx148(UserAvatar, { user: notificationData.actor, className: "h-8 w-8" }) }) }) : /* @__PURE__ */ jsx148("div", { className: "flex w-14 max-w-14 px-2" }),
11298
- /* @__PURE__ */ jsxs88("div", { className: "flex w-full flex-col", children: [
11299
- /* @__PURE__ */ jsx148("p", { className: "text-sm", children: t.rich(`foundations.notification.${notification.notificationType}.description`, {
11300
- strong: /* @__PURE__ */ __name((chunks) => /* @__PURE__ */ jsx148("strong", { children: chunks }), "strong"),
11301
- actor: notificationData.actor?.name ?? "",
11302
- title: notificationData.title
11303
- }) }),
11304
- /* @__PURE__ */ jsx148("div", { className: "text-muted-foreground mt-1 w-full text-xs", children: new Date(notification.createdAt).toLocaleString() })
11440
+ /* @__PURE__ */ jsx147(CardContent, { children: invoices.length === 0 ? /* @__PURE__ */ jsxs89("div", { className: "space-y-2", children: [
11441
+ /* @__PURE__ */ jsx147("p", { className: "text-xl font-bold text-muted-foreground", children: "No invoices yet" }),
11442
+ /* @__PURE__ */ jsx147("p", { className: "text-xs text-muted-foreground", children: "Invoices will appear after your first billing cycle" })
11443
+ ] }) : latestInvoice ? /* @__PURE__ */ jsxs89("div", { className: "space-y-2", children: [
11444
+ /* @__PURE__ */ jsxs89("div", { className: "flex items-center gap-2", children: [
11445
+ /* @__PURE__ */ jsx147("p", { className: "text-xl font-bold", children: formatAmount(latestInvoice.total, latestInvoice.currency) }),
11446
+ /* @__PURE__ */ jsx147(Badge, { variant: getStatusBadgeVariant2(latestInvoice.status), children: latestInvoice.status })
11305
11447
  ] }),
11306
- /* @__PURE__ */ jsxs88("div", { className: "flex flex-row items-center", children: [
11307
- notificationData.url ? /* @__PURE__ */ jsx148(Link2, { href: notificationData.url, children: /* @__PURE__ */ jsx148(Button, { variant: `outline`, size: `sm`, onClick: (e) => e.stopPropagation(), children: t(`foundations.notification.${notification.notificationType}.buttons.action`) }) }) : /* @__PURE__ */ jsx148(Fragment28, {}),
11308
- !archived && /* @__PURE__ */ jsxs88(Tooltip2, { children: [
11309
- /* @__PURE__ */ jsx148(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx148(
11310
- Button,
11311
- {
11312
- variant: `link`,
11313
- onClick: (e) => {
11314
- e.preventDefault();
11315
- e.stopPropagation();
11316
- archiveNotification(notification);
11317
- },
11318
- className: "text-muted-foreground hover:text-destructive ml-2",
11319
- children: /* @__PURE__ */ jsx148(ArchiveIcon, { className: "h-4 w-4 cursor-pointer" })
11320
- }
11321
- ) }),
11322
- /* @__PURE__ */ jsx148(TooltipContent, { children: t(`foundations.notification.buttons.archive`) })
11448
+ /* @__PURE__ */ jsx147("p", { className: "text-sm text-muted-foreground", children: latestInvoice.stripeInvoiceNumber || `Invoice from ${formatDate2(latestInvoice.periodStart)}` }),
11449
+ /* @__PURE__ */ jsxs89("div", { className: "flex items-center gap-4 text-xs text-muted-foreground", children: [
11450
+ paidInvoices.length > 0 && /* @__PURE__ */ jsxs89("span", { children: [
11451
+ paidInvoices.length,
11452
+ " paid"
11453
+ ] }),
11454
+ openInvoices.length > 0 && /* @__PURE__ */ jsxs89("span", { className: "text-orange-600", children: [
11455
+ openInvoices.length,
11456
+ " open"
11457
+ ] }),
11458
+ /* @__PURE__ */ jsxs89("span", { className: "flex items-center", children: [
11459
+ "View all",
11460
+ /* @__PURE__ */ jsx147(ChevronRight3, { className: "h-3 w-3 ml-1" })
11323
11461
  ] })
11324
11462
  ] })
11325
- ] }) }) }, notification.id);
11326
- }) : /* @__PURE__ */ jsx148(LoadingSkeleton, {}) });
11463
+ ] }) : null })
11464
+ ] });
11327
11465
  }
11328
- __name(NotificationsList, "NotificationsList");
11329
-
11330
- // src/features/notification/components/containers/NotificationsListContainer.tsx
11331
- import { jsx as jsx149, jsxs as jsxs89 } from "react/jsx-runtime";
11332
- function NotificationsListContainerContent() {
11333
- const t = useTranslations57();
11334
- const { notifications, isLoading, error } = useNotificationContext();
11466
+ __name(InvoicesSummaryCard, "InvoicesSummaryCard");
11467
+
11468
+ // src/features/billing/components/cards/BillingUsageSummaryCard.tsx
11469
+ import { Activity, ChevronRight as ChevronRight4 } from "lucide-react";
11470
+ import { jsx as jsx148, jsxs as jsxs90 } from "react/jsx-runtime";
11471
+ function formatNumber(value) {
11472
+ return new Intl.NumberFormat(void 0, {
11473
+ notation: "compact",
11474
+ compactDisplay: "short"
11475
+ }).format(value);
11476
+ }
11477
+ __name(formatNumber, "formatNumber");
11478
+ function BillingUsageSummaryCard({
11479
+ meters,
11480
+ summaries,
11481
+ loading,
11482
+ error,
11483
+ onViewDetailsClick
11484
+ }) {
11485
+ if (loading) {
11486
+ return /* @__PURE__ */ jsxs90(Card, { children: [
11487
+ /* @__PURE__ */ jsxs90(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11488
+ /* @__PURE__ */ jsx148(CardTitle, { className: "text-sm font-medium", children: "Usage This Month" }),
11489
+ /* @__PURE__ */ jsx148(Activity, { className: "h-4 w-4 text-muted-foreground" })
11490
+ ] }),
11491
+ /* @__PURE__ */ jsxs90(CardContent, { children: [
11492
+ /* @__PURE__ */ jsx148(Skeleton, { className: "h-6 w-24 mb-2" }),
11493
+ /* @__PURE__ */ jsx148(Skeleton, { className: "h-4 w-32" })
11494
+ ] })
11495
+ ] });
11496
+ }
11335
11497
  if (error) {
11336
- return /* @__PURE__ */ jsx149("div", { className: "flex items-center justify-center p-8 text-center", children: /* @__PURE__ */ jsxs89("div", { className: "text-destructive text-sm", children: [
11337
- /* @__PURE__ */ jsxs89("p", { children: [
11338
- "Error loading notifications: ",
11339
- error
11498
+ return /* @__PURE__ */ jsxs90(Card, { children: [
11499
+ /* @__PURE__ */ jsxs90(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11500
+ /* @__PURE__ */ jsx148(CardTitle, { className: "text-sm font-medium", children: "Usage This Month" }),
11501
+ /* @__PURE__ */ jsx148(Activity, { className: "h-4 w-4 text-muted-foreground" })
11340
11502
  ] }),
11341
- /* @__PURE__ */ jsx149("p", { className: "text-muted-foreground mt-2", children: "Please try refreshing the page." })
11342
- ] }) });
11503
+ /* @__PURE__ */ jsx148(CardContent, { children: /* @__PURE__ */ jsx148("p", { className: "text-sm text-destructive", children: error }) })
11504
+ ] });
11343
11505
  }
11344
- const tabs = [
11345
- {
11346
- label: t(`foundations.notification.inbox`),
11347
- content: /* @__PURE__ */ jsx149(NotificationsList, { archived: false })
11348
- },
11349
- {
11350
- label: t(`foundations.notification.archived`),
11351
- content: /* @__PURE__ */ jsx149(NotificationsList, { archived: true })
11352
- }
11353
- ];
11354
- return /* @__PURE__ */ jsx149(TabsContainer, { tabs });
11355
- }
11356
- __name(NotificationsListContainerContent, "NotificationsListContainerContent");
11357
- function NotificationsListContainer() {
11358
- return /* @__PURE__ */ jsx149(NotificationErrorBoundary, { children: /* @__PURE__ */ jsx149(NotificationsListContainerContent, {}) });
11506
+ const totalUsage = Object.values(summaries).reduce((acc, summary) => {
11507
+ return acc + (summary?.aggregatedValue || 0);
11508
+ }, 0);
11509
+ const primaryMeter = meters.find((m) => summaries[m.id]?.aggregatedValue);
11510
+ const primarySummary = primaryMeter ? summaries[primaryMeter.id] : null;
11511
+ return /* @__PURE__ */ jsxs90(Card, { className: "cursor-pointer hover:bg-accent/50 transition-colors", onClick: onViewDetailsClick, children: [
11512
+ /* @__PURE__ */ jsxs90(CardHeader, { className: "flex flex-row items-center justify-between space-y-0 pb-2", children: [
11513
+ /* @__PURE__ */ jsx148(CardTitle, { className: "text-sm font-medium", children: "Usage This Month" }),
11514
+ /* @__PURE__ */ jsx148(Activity, { className: "h-4 w-4 text-muted-foreground" })
11515
+ ] }),
11516
+ /* @__PURE__ */ jsx148(CardContent, { children: meters.length === 0 ? /* @__PURE__ */ jsxs90("div", { className: "space-y-2", children: [
11517
+ /* @__PURE__ */ jsx148("p", { className: "text-xl font-bold text-muted-foreground", children: "No meters" }),
11518
+ /* @__PURE__ */ jsx148("p", { className: "text-xs text-muted-foreground", children: "No usage meters are configured" })
11519
+ ] }) : /* @__PURE__ */ jsxs90("div", { className: "space-y-2", children: [
11520
+ /* @__PURE__ */ jsxs90("p", { className: "text-xl font-bold", children: [
11521
+ formatNumber(totalUsage),
11522
+ " units"
11523
+ ] }),
11524
+ primaryMeter && primarySummary && /* @__PURE__ */ jsxs90("p", { className: "text-sm text-muted-foreground", children: [
11525
+ primaryMeter.displayName,
11526
+ ": ",
11527
+ formatNumber(primarySummary.aggregatedValue)
11528
+ ] }),
11529
+ meters.length > 1 && /* @__PURE__ */ jsxs90("p", { className: "text-xs text-muted-foreground", children: [
11530
+ "Across ",
11531
+ meters.length,
11532
+ " meters"
11533
+ ] }),
11534
+ /* @__PURE__ */ jsxs90("span", { className: "flex items-center text-xs text-muted-foreground", children: [
11535
+ "View details",
11536
+ /* @__PURE__ */ jsx148(ChevronRight4, { className: "h-3 w-3 ml-1" })
11537
+ ] })
11538
+ ] }) })
11539
+ ] });
11540
+ }
11541
+ __name(BillingUsageSummaryCard, "BillingUsageSummaryCard");
11542
+
11543
+ // src/features/billing/components/containers/BillingDashboardContainer.tsx
11544
+ import { CreditCard as CreditCard4, Loader2 as Loader24, Wallet as Wallet2 } from "lucide-react";
11545
+ import { useCallback as useCallback18, useEffect as useEffect47, useState as useState62 } from "react";
11546
+
11547
+ // src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
11548
+ import { CreditCard as CreditCard2 } from "lucide-react";
11549
+ import { useEffect as useEffect42, useState as useState52 } from "react";
11550
+
11551
+ // src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx
11552
+ import { CardElement, useElements, useStripe } from "@stripe/react-stripe-js";
11553
+ import { useEffect as useEffect40, useState as useState50 } from "react";
11554
+ import { jsx as jsx149, jsxs as jsxs91 } from "react/jsx-runtime";
11555
+ function PaymentMethodEditor({ open, onOpenChange, onSuccess }) {
11556
+ const stripe = useStripe();
11557
+ const elements = useElements();
11558
+ const [setupIntent, setSetupIntent] = useState50(null);
11559
+ const [loading, setLoading] = useState50(true);
11560
+ const [isSubmitting, setIsSubmitting] = useState50(false);
11561
+ const [error, setError] = useState50(null);
11562
+ const [setAsDefault, setSetAsDefault] = useState50(true);
11563
+ useEffect40(() => {
11564
+ const fetchSetupIntent = /* @__PURE__ */ __name(async () => {
11565
+ setLoading(true);
11566
+ try {
11567
+ const intent = await StripeCustomerService.createSetupIntent();
11568
+ setSetupIntent(intent);
11569
+ } catch (err) {
11570
+ console.error("[PaymentMethodEditor] Failed to create setup intent:", err);
11571
+ setError("Failed to initialize payment form. Please try again.");
11572
+ } finally {
11573
+ setLoading(false);
11574
+ }
11575
+ }, "fetchSetupIntent");
11576
+ if (open) {
11577
+ fetchSetupIntent();
11578
+ }
11579
+ }, [open]);
11580
+ const handleSubmit = /* @__PURE__ */ __name(async (e) => {
11581
+ e.preventDefault();
11582
+ if (!stripe || !elements || !setupIntent) {
11583
+ return;
11584
+ }
11585
+ setIsSubmitting(true);
11586
+ setError(null);
11587
+ try {
11588
+ const cardElement = elements.getElement(CardElement);
11589
+ if (!cardElement) {
11590
+ throw new Error("Card element not found");
11591
+ }
11592
+ const { error: stripeError, setupIntent: confirmedSetupIntent } = await stripe.confirmCardSetup(
11593
+ setupIntent.clientSecret,
11594
+ {
11595
+ payment_method: {
11596
+ card: cardElement
11597
+ }
11598
+ }
11599
+ );
11600
+ if (stripeError) {
11601
+ console.error("[PaymentMethodEditor] Stripe error:", stripeError);
11602
+ setError(stripeError.message || "Failed to add payment method. Please check your card details.");
11603
+ setIsSubmitting(false);
11604
+ return;
11605
+ }
11606
+ if (setAsDefault && confirmedSetupIntent?.payment_method) {
11607
+ await StripeCustomerService.setDefaultPaymentMethod({
11608
+ paymentMethodId: typeof confirmedSetupIntent.payment_method === "string" ? confirmedSetupIntent.payment_method : confirmedSetupIntent.payment_method.id
11609
+ });
11610
+ }
11611
+ onSuccess();
11612
+ onOpenChange(false);
11613
+ } catch (err) {
11614
+ console.error("[PaymentMethodEditor] Error:", err);
11615
+ setError(err.message || "An unexpected error occurred. Please try again.");
11616
+ } finally {
11617
+ setIsSubmitting(false);
11618
+ }
11619
+ }, "handleSubmit");
11620
+ return /* @__PURE__ */ jsx149(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs91(DialogContent, { className: "max-w-md", children: [
11621
+ /* @__PURE__ */ jsxs91(DialogHeader, { children: [
11622
+ /* @__PURE__ */ jsx149(DialogTitle, { children: "Add Payment Method" }),
11623
+ /* @__PURE__ */ jsx149(DialogDescription, { children: "Add a new payment method to your account. Your card information is securely processed by Stripe." })
11624
+ ] }),
11625
+ loading && /* @__PURE__ */ jsx149("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx149("p", { className: "text-muted-foreground", children: "Loading payment form..." }) }),
11626
+ !loading && setupIntent && /* @__PURE__ */ jsxs91("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
11627
+ /* @__PURE__ */ jsx149("div", { className: "rounded-md border border-gray-300 p-3", children: /* @__PURE__ */ jsx149(
11628
+ CardElement,
11629
+ {
11630
+ options: {
11631
+ style: {
11632
+ base: {
11633
+ fontSize: "16px",
11634
+ color: "#424770",
11635
+ "::placeholder": {
11636
+ color: "#aab7c4"
11637
+ }
11638
+ },
11639
+ invalid: {
11640
+ color: "#9e2146"
11641
+ }
11642
+ }
11643
+ }
11644
+ }
11645
+ ) }),
11646
+ /* @__PURE__ */ jsxs91("div", { className: "flex items-center gap-x-2", children: [
11647
+ /* @__PURE__ */ jsx149(
11648
+ Checkbox,
11649
+ {
11650
+ id: "setAsDefault",
11651
+ checked: setAsDefault,
11652
+ onCheckedChange: (checked) => setSetAsDefault(!!checked)
11653
+ }
11654
+ ),
11655
+ /* @__PURE__ */ jsx149(Label3, { htmlFor: "setAsDefault", className: "text-sm font-normal", children: "Set as default payment method" })
11656
+ ] }),
11657
+ error && /* @__PURE__ */ jsx149(Alert, { variant: "destructive", className: "bg-red-50 border-red-200", children: /* @__PURE__ */ jsx149(AlertDescription, { children: error }) }),
11658
+ /* @__PURE__ */ jsxs91("div", { className: "flex justify-end gap-x-2", children: [
11659
+ /* @__PURE__ */ jsx149(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
11660
+ /* @__PURE__ */ jsx149(Button, { type: "submit", disabled: !stripe || isSubmitting, children: isSubmitting ? "Processing..." : "Add Card" })
11661
+ ] })
11662
+ ] }),
11663
+ !loading && !setupIntent && error && /* @__PURE__ */ jsx149(Alert, { variant: "destructive", className: "bg-red-50 border-red-200", children: /* @__PURE__ */ jsx149(AlertDescription, { children: error }) })
11664
+ ] }) });
11665
+ }
11666
+ __name(PaymentMethodEditor, "PaymentMethodEditor");
11667
+
11668
+ // src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx
11669
+ import { MoreVertical } from "lucide-react";
11670
+ import { useEffect as useEffect41, useState as useState51 } from "react";
11671
+ import { Fragment as Fragment28, jsx as jsx150, jsxs as jsxs92 } from "react/jsx-runtime";
11672
+ var brandIcons = {
11673
+ visa: "\u{1F4B3}",
11674
+ mastercard: "\u{1F4B3}",
11675
+ amex: "\u{1F4B3}",
11676
+ discover: "\u{1F4B3}"
11677
+ };
11678
+ function PaymentMethodCard({ paymentMethod, onUpdate }) {
11679
+ const [loading, setLoading] = useState51(false);
11680
+ const [customer, setCustomer] = useState51(null);
11681
+ const [showRemoveDialog, setShowRemoveDialog] = useState51(false);
11682
+ useEffect41(() => {
11683
+ const loadCustomer = /* @__PURE__ */ __name(async () => {
11684
+ try {
11685
+ const fetchedCustomer = await StripeCustomerService.getCustomer();
11686
+ setCustomer(fetchedCustomer);
11687
+ } catch (error) {
11688
+ console.error("[PaymentMethodCard] Failed to load customer:", error);
11689
+ }
11690
+ }, "loadCustomer");
11691
+ loadCustomer();
11692
+ }, []);
11693
+ const isDefault = customer?.defaultPaymentMethodId === paymentMethod.id;
11694
+ const brand = paymentMethod.card?.brand || "card";
11695
+ const last4 = paymentMethod.card?.last4 || "****";
11696
+ const expMonth = paymentMethod.card?.expMonth || 0;
11697
+ const expYear = paymentMethod.card?.expYear || 0;
11698
+ const brandIcon = brandIcons[brand.toLowerCase()] || "\u{1F4B3}";
11699
+ const handleSetDefault = /* @__PURE__ */ __name(async () => {
11700
+ setLoading(true);
11701
+ try {
11702
+ await StripeCustomerService.setDefaultPaymentMethod({ paymentMethodId: paymentMethod.id });
11703
+ onUpdate();
11704
+ } catch (error) {
11705
+ console.error("[PaymentMethodCard] Failed to set as default:", error);
11706
+ } finally {
11707
+ setLoading(false);
11708
+ }
11709
+ }, "handleSetDefault");
11710
+ const handleRemove = /* @__PURE__ */ __name(async () => {
11711
+ setLoading(true);
11712
+ try {
11713
+ await StripeCustomerService.removePaymentMethod({ paymentMethodId: paymentMethod.id });
11714
+ setShowRemoveDialog(false);
11715
+ onUpdate();
11716
+ } catch (error) {
11717
+ console.error("[PaymentMethodCard] Failed to remove:", error);
11718
+ setLoading(false);
11719
+ }
11720
+ }, "handleRemove");
11721
+ return /* @__PURE__ */ jsxs92(Fragment28, { children: [
11722
+ /* @__PURE__ */ jsxs92(Card, { className: "relative", children: [
11723
+ isDefault && /* @__PURE__ */ jsx150(Badge, { className: "absolute right-2 top-2 bg-green-100 text-green-800 hover:bg-green-100", children: "Default" }),
11724
+ /* @__PURE__ */ jsxs92(CardHeader, { className: "flex flex-row items-center justify-between pb-2", children: [
11725
+ /* @__PURE__ */ jsxs92("div", { className: "flex items-center gap-x-2", children: [
11726
+ /* @__PURE__ */ jsx150("span", { className: "text-2xl", children: brandIcon }),
11727
+ /* @__PURE__ */ jsx150("span", { className: "text-sm font-medium capitalize", children: brand })
11728
+ ] }),
11729
+ /* @__PURE__ */ jsxs92(DropdownMenu, { children: [
11730
+ /* @__PURE__ */ jsx150(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx150(Button, { variant: "ghost", size: "sm", disabled: loading, className: "h-8 w-8 p-0", children: /* @__PURE__ */ jsx150(MoreVertical, { className: "h-4 w-4" }) }) }),
11731
+ /* @__PURE__ */ jsxs92(DropdownMenuContent, { align: "end", children: [
11732
+ !isDefault && /* @__PURE__ */ jsx150(DropdownMenuItem, { onClick: handleSetDefault, disabled: loading, children: "Set as Default" }),
11733
+ /* @__PURE__ */ jsx150(DropdownMenuItem, { onClick: () => setShowRemoveDialog(true), disabled: loading, className: "text-red-600", children: "Remove" })
11734
+ ] })
11735
+ ] })
11736
+ ] }),
11737
+ /* @__PURE__ */ jsx150(CardContent, { children: /* @__PURE__ */ jsxs92("div", { className: "flex flex-col gap-y-1", children: [
11738
+ /* @__PURE__ */ jsxs92("p", { className: "text-lg font-semibold", children: [
11739
+ "\u2022\u2022\u2022\u2022 ",
11740
+ last4
11741
+ ] }),
11742
+ /* @__PURE__ */ jsxs92("p", { className: "text-sm text-muted-foreground", children: [
11743
+ "Expires ",
11744
+ String(expMonth).padStart(2, "0"),
11745
+ "/",
11746
+ expYear
11747
+ ] })
11748
+ ] }) })
11749
+ ] }),
11750
+ /* @__PURE__ */ jsx150(AlertDialog, { open: showRemoveDialog, onOpenChange: setShowRemoveDialog, children: /* @__PURE__ */ jsxs92(AlertDialogContent, { children: [
11751
+ /* @__PURE__ */ jsxs92(AlertDialogHeader, { children: [
11752
+ /* @__PURE__ */ jsx150(AlertDialogTitle, { children: "Remove Payment Method" }),
11753
+ /* @__PURE__ */ jsxs92(AlertDialogDescription, { children: [
11754
+ "Are you sure you want to remove this payment method? This action cannot be undone.",
11755
+ isDefault && " This is your default payment method."
11756
+ ] })
11757
+ ] }),
11758
+ /* @__PURE__ */ jsxs92(AlertDialogFooter, { children: [
11759
+ /* @__PURE__ */ jsx150(AlertDialogCancel, { disabled: loading, children: "Cancel" }),
11760
+ /* @__PURE__ */ jsx150(AlertDialogAction, { onClick: handleRemove, disabled: loading, className: "bg-red-600 hover:bg-red-700", children: loading ? "Removing..." : "Remove" })
11761
+ ] })
11762
+ ] }) })
11763
+ ] });
11764
+ }
11765
+ __name(PaymentMethodCard, "PaymentMethodCard");
11766
+
11767
+ // src/features/billing/stripe-customer/components/lists/PaymentMethodsList.tsx
11768
+ import { jsx as jsx151 } from "react/jsx-runtime";
11769
+ function PaymentMethodsList({ paymentMethods, onUpdate }) {
11770
+ return /* @__PURE__ */ jsx151("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-3", children: paymentMethods.map((paymentMethod) => /* @__PURE__ */ jsx151(PaymentMethodCard, { paymentMethod, onUpdate }, paymentMethod.id)) });
11771
+ }
11772
+ __name(PaymentMethodsList, "PaymentMethodsList");
11773
+
11774
+ // src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx
11775
+ import { jsx as jsx152, jsxs as jsxs93 } from "react/jsx-runtime";
11776
+ function PaymentMethodsContainer() {
11777
+ const [paymentMethods, setPaymentMethods] = useState52([]);
11778
+ const [loading, setLoading] = useState52(true);
11779
+ const [showAddPaymentMethod, setShowAddPaymentMethod] = useState52(false);
11780
+ const loadPaymentMethods = /* @__PURE__ */ __name(async () => {
11781
+ setLoading(true);
11782
+ try {
11783
+ const fetchedPaymentMethods = await StripeCustomerService.listPaymentMethods();
11784
+ setPaymentMethods(fetchedPaymentMethods);
11785
+ } catch (error) {
11786
+ console.error("[PaymentMethodsContainer] Failed to load payment methods:", error);
11787
+ } finally {
11788
+ setLoading(false);
11789
+ }
11790
+ }, "loadPaymentMethods");
11791
+ useEffect42(() => {
11792
+ loadPaymentMethods();
11793
+ }, []);
11794
+ if (loading) {
11795
+ return /* @__PURE__ */ jsx152("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx152("p", { className: "text-muted-foreground", children: "Loading payment methods..." }) });
11796
+ }
11797
+ return /* @__PURE__ */ jsxs93("div", { className: "flex w-full flex-col gap-y-6", children: [
11798
+ /* @__PURE__ */ jsxs93("div", { className: "flex items-center justify-between", children: [
11799
+ /* @__PURE__ */ jsxs93("div", { className: "flex items-center gap-x-3", children: [
11800
+ /* @__PURE__ */ jsx152(CreditCard2, { className: "h-8 w-8" }),
11801
+ /* @__PURE__ */ jsx152("h1", { className: "text-3xl font-bold", children: "Payment Methods" })
11802
+ ] }),
11803
+ /* @__PURE__ */ jsx152(Button, { onClick: () => setShowAddPaymentMethod(true), children: "Add Payment Method" })
11804
+ ] }),
11805
+ paymentMethods.length === 0 && /* @__PURE__ */ jsxs93("div", { className: "flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed border-gray-300 bg-muted/50 p-12", children: [
11806
+ /* @__PURE__ */ jsx152(CreditCard2, { className: "h-16 w-16 text-muted-foreground" }),
11807
+ /* @__PURE__ */ jsxs93("div", { className: "text-center", children: [
11808
+ /* @__PURE__ */ jsx152("h3", { className: "mb-2 text-xl font-semibold", children: "No payment methods" }),
11809
+ /* @__PURE__ */ jsx152("p", { className: "mb-4 text-muted-foreground", children: "Add a payment method to enable subscriptions and secure checkout." }),
11810
+ /* @__PURE__ */ jsx152(Button, { onClick: () => setShowAddPaymentMethod(true), children: "Add Your First Card" })
11811
+ ] })
11812
+ ] }),
11813
+ paymentMethods.length > 0 && /* @__PURE__ */ jsx152(PaymentMethodsList, { paymentMethods, onUpdate: loadPaymentMethods }),
11814
+ showAddPaymentMethod && /* @__PURE__ */ jsx152(
11815
+ PaymentMethodEditor,
11816
+ {
11817
+ open: showAddPaymentMethod,
11818
+ onOpenChange: setShowAddPaymentMethod,
11819
+ onSuccess: loadPaymentMethods
11820
+ }
11821
+ )
11822
+ ] });
11823
+ }
11824
+ __name(PaymentMethodsContainer, "PaymentMethodsContainer");
11825
+
11826
+ // src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx
11827
+ import { useEffect as useEffect43, useState as useState54 } from "react";
11828
+
11829
+ // src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx
11830
+ import { useState as useState53 } from "react";
11831
+
11832
+ // src/features/billing/components/utils/currency.ts
11833
+ function formatInterval(price) {
11834
+ if (price.priceType === "one_time" || !price.recurring) {
11835
+ return "one-time";
11836
+ }
11837
+ const { interval, intervalCount } = price.recurring;
11838
+ if (intervalCount === 1) {
11839
+ return `/${interval}`;
11840
+ }
11841
+ const pluralInterval = interval === "day" ? "days" : interval === "week" ? "weeks" : interval === "month" ? "months" : "years";
11842
+ return `/${intervalCount} ${pluralInterval}`;
11843
+ }
11844
+ __name(formatInterval, "formatInterval");
11845
+ function formatCurrency(amount, currency) {
11846
+ if (amount === void 0) return "$0.00";
11847
+ const dollars = amount / 100;
11848
+ try {
11849
+ return new Intl.NumberFormat("en-US", {
11850
+ style: "currency",
11851
+ currency: currency.toUpperCase(),
11852
+ minimumFractionDigits: 2,
11853
+ maximumFractionDigits: 2
11854
+ }).format(dollars);
11855
+ } catch (error) {
11856
+ console.error("Error formatting currency:", error);
11857
+ return `$${dollars.toFixed(2)}`;
11858
+ }
11859
+ }
11860
+ __name(formatCurrency, "formatCurrency");
11861
+
11862
+ // src/features/billing/components/utils/date.ts
11863
+ function formatDate3(date) {
11864
+ if (!date) return "N/A";
11865
+ const dateObj = typeof date === "string" ? new Date(date) : date;
11866
+ try {
11867
+ return new Intl.DateTimeFormat("en-US", {
11868
+ month: "short",
11869
+ day: "numeric",
11870
+ year: "numeric"
11871
+ }).format(dateObj);
11872
+ } catch (error) {
11873
+ console.error("Error formatting date:", error);
11874
+ return "Invalid Date";
11875
+ }
11876
+ }
11877
+ __name(formatDate3, "formatDate");
11878
+
11879
+ // src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx
11880
+ import { Download, ExternalLink as ExternalLink2, RefreshCw as RefreshCw2 } from "lucide-react";
11881
+
11882
+ // src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx
11883
+ import { jsx as jsx153 } from "react/jsx-runtime";
11884
+ var statusConfig = {
11885
+ ["draft" /* DRAFT */]: {
11886
+ label: "Draft",
11887
+ color: "bg-gray-100 text-gray-800"
11888
+ },
11889
+ ["open" /* OPEN */]: {
11890
+ label: "Open",
11891
+ color: "bg-blue-100 text-blue-800"
11892
+ },
11893
+ ["paid" /* PAID */]: {
11894
+ label: "Paid",
11895
+ color: "bg-green-100 text-green-800"
11896
+ },
11897
+ ["void" /* VOID */]: {
11898
+ label: "Void",
11899
+ color: "bg-gray-100 text-gray-800"
11900
+ },
11901
+ ["uncollectible" /* UNCOLLECTIBLE */]: {
11902
+ label: "Uncollectible",
11903
+ color: "bg-red-100 text-red-800"
11904
+ }
11905
+ };
11906
+ function InvoiceStatusBadge({ status }) {
11907
+ const config = statusConfig[status] || statusConfig["draft" /* DRAFT */];
11908
+ return /* @__PURE__ */ jsx153("span", { className: `${config.color} text-xs px-2 py-1 rounded-full font-medium`, children: config.label });
11909
+ }
11910
+ __name(InvoiceStatusBadge, "InvoiceStatusBadge");
11911
+
11912
+ // src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx
11913
+ import { jsx as jsx154, jsxs as jsxs94 } from "react/jsx-runtime";
11914
+ function InvoiceDetails({ invoice, open, onOpenChange, onInvoiceChange }) {
11915
+ const handleDownloadPDF = /* @__PURE__ */ __name(() => {
11916
+ if (invoice.stripePdfUrl) {
11917
+ window.open(invoice.stripePdfUrl, "_blank");
11918
+ }
11919
+ }, "handleDownloadPDF");
11920
+ const handleRetryPayment = /* @__PURE__ */ __name(async () => {
11921
+ }, "handleRetryPayment");
11922
+ const handleViewInStripe = /* @__PURE__ */ __name(() => {
11923
+ if (invoice.stripeHostedInvoiceUrl) {
11924
+ window.open(invoice.stripeHostedInvoiceUrl, "_blank");
11925
+ }
11926
+ }, "handleViewInStripe");
11927
+ const getInvoiceNumber = /* @__PURE__ */ __name(() => {
11928
+ if (invoice.stripeInvoiceNumber) {
11929
+ return invoice.stripeInvoiceNumber;
11930
+ }
11931
+ return invoice.stripeInvoiceId.slice(-8);
11932
+ }, "getInvoiceNumber");
11933
+ const productName = invoice.subscription?.price?.product?.name || "Subscription";
11934
+ return /* @__PURE__ */ jsx154(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs94(DialogContent, { className: "max-w-2xl", children: [
11935
+ /* @__PURE__ */ jsxs94(DialogHeader, { children: [
11936
+ /* @__PURE__ */ jsxs94(DialogTitle, { children: [
11937
+ "Invoice ",
11938
+ getInvoiceNumber()
11939
+ ] }),
11940
+ /* @__PURE__ */ jsx154(DialogDescription, { children: formatDate3(invoice.periodStart) })
11941
+ ] }),
11942
+ /* @__PURE__ */ jsxs94("div", { className: "space-y-6", children: [
11943
+ /* @__PURE__ */ jsxs94("div", { className: "flex items-center gap-x-3", children: [
11944
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Status:" }),
11945
+ /* @__PURE__ */ jsx154(InvoiceStatusBadge, { status: invoice.status })
11946
+ ] }),
11947
+ /* @__PURE__ */ jsxs94("div", { className: "grid grid-cols-2 gap-4", children: [
11948
+ /* @__PURE__ */ jsxs94("div", { children: [
11949
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Billing Period:" }),
11950
+ /* @__PURE__ */ jsxs94("p", { className: "font-medium", children: [
11951
+ formatDate3(invoice.periodStart),
11952
+ " - ",
11953
+ formatDate3(invoice.periodEnd)
11954
+ ] })
11955
+ ] }),
11956
+ invoice.dueDate && /* @__PURE__ */ jsxs94("div", { children: [
11957
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Due Date:" }),
11958
+ /* @__PURE__ */ jsx154("p", { className: "font-medium", children: formatDate3(invoice.dueDate) })
11959
+ ] }),
11960
+ invoice.paidAt && /* @__PURE__ */ jsxs94("div", { children: [
11961
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Paid Date:" }),
11962
+ /* @__PURE__ */ jsx154("p", { className: "font-medium", children: formatDate3(invoice.paidAt) })
11963
+ ] }),
11964
+ /* @__PURE__ */ jsxs94("div", { children: [
11965
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Attempt Count:" }),
11966
+ /* @__PURE__ */ jsx154("p", { className: "font-medium", children: invoice.attemptCount })
11967
+ ] })
11968
+ ] }),
11969
+ /* @__PURE__ */ jsxs94("div", { children: [
11970
+ /* @__PURE__ */ jsx154("h4", { className: "text-sm font-medium text-muted-foreground mb-2", children: "Line Items" }),
11971
+ /* @__PURE__ */ jsx154("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs94("table", { className: "w-full", children: [
11972
+ /* @__PURE__ */ jsx154("thead", { className: "bg-muted", children: /* @__PURE__ */ jsxs94("tr", { children: [
11973
+ /* @__PURE__ */ jsx154("th", { className: "text-left p-3 text-sm font-medium", children: "Description" }),
11974
+ /* @__PURE__ */ jsx154("th", { className: "text-right p-3 text-sm font-medium", children: "Amount" })
11975
+ ] }) }),
11976
+ /* @__PURE__ */ jsx154("tbody", { children: /* @__PURE__ */ jsxs94("tr", { className: "border-t", children: [
11977
+ /* @__PURE__ */ jsx154("td", { className: "p-3", children: productName }),
11978
+ /* @__PURE__ */ jsx154("td", { className: "p-3 text-right", children: formatCurrency(invoice.subtotal, invoice.currency) })
11979
+ ] }) })
11980
+ ] }) })
11981
+ ] }),
11982
+ /* @__PURE__ */ jsxs94("div", { className: "space-y-2 border-t pt-4", children: [
11983
+ /* @__PURE__ */ jsxs94("div", { className: "flex justify-between", children: [
11984
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Subtotal:" }),
11985
+ /* @__PURE__ */ jsx154("span", { className: "font-medium", children: formatCurrency(invoice.subtotal, invoice.currency) })
11986
+ ] }),
11987
+ invoice.tax !== void 0 && invoice.tax > 0 && /* @__PURE__ */ jsxs94("div", { className: "flex justify-between", children: [
11988
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Tax:" }),
11989
+ /* @__PURE__ */ jsx154("span", { className: "font-medium", children: formatCurrency(invoice.tax, invoice.currency) })
11990
+ ] }),
11991
+ /* @__PURE__ */ jsxs94("div", { className: "flex justify-between text-lg font-semibold border-t pt-2", children: [
11992
+ /* @__PURE__ */ jsx154("span", { children: "Total:" }),
11993
+ /* @__PURE__ */ jsx154("span", { children: formatCurrency(invoice.total, invoice.currency) })
11994
+ ] }),
11995
+ invoice.amountPaid > 0 && /* @__PURE__ */ jsxs94("div", { className: "flex justify-between", children: [
11996
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Amount Paid:" }),
11997
+ /* @__PURE__ */ jsx154("span", { className: "font-medium text-green-600", children: formatCurrency(invoice.amountPaid, invoice.currency) })
11998
+ ] }),
11999
+ invoice.amountRemaining > 0 && /* @__PURE__ */ jsxs94("div", { className: "flex justify-between", children: [
12000
+ /* @__PURE__ */ jsx154("span", { className: "text-sm font-medium text-muted-foreground", children: "Amount Due:" }),
12001
+ /* @__PURE__ */ jsx154("span", { className: "font-medium text-red-600", children: formatCurrency(invoice.amountRemaining, invoice.currency) })
12002
+ ] })
12003
+ ] }),
12004
+ /* @__PURE__ */ jsxs94("div", { className: "flex flex-wrap gap-2 pt-4 border-t", children: [
12005
+ invoice.stripePdfUrl && /* @__PURE__ */ jsxs94(Button, { variant: "outline", onClick: handleDownloadPDF, children: [
12006
+ /* @__PURE__ */ jsx154(Download, { className: "mr-2 h-4 w-4" }),
12007
+ "Download PDF"
12008
+ ] }),
12009
+ invoice.status === "open" /* OPEN */ && invoice.attempted && /* @__PURE__ */ jsxs94(Button, { variant: "default", onClick: handleRetryPayment, children: [
12010
+ /* @__PURE__ */ jsx154(RefreshCw2, { className: "mr-2 h-4 w-4" }),
12011
+ "Retry Payment"
12012
+ ] }),
12013
+ invoice.stripeHostedInvoiceUrl && /* @__PURE__ */ jsxs94(Button, { variant: "outline", onClick: handleViewInStripe, children: [
12014
+ /* @__PURE__ */ jsx154(ExternalLink2, { className: "mr-2 h-4 w-4" }),
12015
+ "View in Stripe"
12016
+ ] })
12017
+ ] })
12018
+ ] })
12019
+ ] }) });
12020
+ }
12021
+ __name(InvoiceDetails, "InvoiceDetails");
12022
+
12023
+ // src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx
12024
+ import { Fragment as Fragment29, jsx as jsx155, jsxs as jsxs95 } from "react/jsx-runtime";
12025
+ function InvoicesList({ invoices, onInvoicesChange }) {
12026
+ const [selectedInvoice, setSelectedInvoice] = useState53(null);
12027
+ const handleRowClick = /* @__PURE__ */ __name((invoice) => {
12028
+ setSelectedInvoice(invoice);
12029
+ }, "handleRowClick");
12030
+ const getInvoiceNumber = /* @__PURE__ */ __name((invoice) => {
12031
+ if (invoice.stripeInvoiceNumber) {
12032
+ return invoice.stripeInvoiceNumber;
12033
+ }
12034
+ return invoice.stripeInvoiceId.slice(-8);
12035
+ }, "getInvoiceNumber");
12036
+ return /* @__PURE__ */ jsxs95(Fragment29, { children: [
12037
+ /* @__PURE__ */ jsx155("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs95(Table, { children: [
12038
+ /* @__PURE__ */ jsx155(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs95(TableRow, { children: [
12039
+ /* @__PURE__ */ jsx155(TableHead, { children: "Invoice #" }),
12040
+ /* @__PURE__ */ jsx155(TableHead, { children: "Date" }),
12041
+ /* @__PURE__ */ jsx155(TableHead, { children: "Status" }),
12042
+ /* @__PURE__ */ jsx155(TableHead, { className: "text-right", children: "Amount" }),
12043
+ /* @__PURE__ */ jsx155(TableHead, { children: "Period" })
12044
+ ] }) }),
12045
+ /* @__PURE__ */ jsx155(TableBody, { children: invoices.map((invoice) => {
12046
+ const invoiceNumber = getInvoiceNumber(invoice);
12047
+ const date = formatDate3(invoice.periodStart);
12048
+ const amount = formatCurrency(invoice.total, invoice.currency);
12049
+ const period = `${formatDate3(invoice.periodStart)} - ${formatDate3(invoice.periodEnd)}`;
12050
+ return /* @__PURE__ */ jsxs95(
12051
+ TableRow,
12052
+ {
12053
+ onClick: () => handleRowClick(invoice),
12054
+ className: "cursor-pointer hover:bg-muted/50",
12055
+ children: [
12056
+ /* @__PURE__ */ jsx155(TableCell, { className: "font-medium", children: invoiceNumber }),
12057
+ /* @__PURE__ */ jsx155(TableCell, { className: "text-muted-foreground text-sm", children: date }),
12058
+ /* @__PURE__ */ jsx155(TableCell, { children: /* @__PURE__ */ jsx155(InvoiceStatusBadge, { status: invoice.status }) }),
12059
+ /* @__PURE__ */ jsx155(TableCell, { className: "text-right font-medium", children: amount }),
12060
+ /* @__PURE__ */ jsx155(TableCell, { className: "text-muted-foreground text-sm", children: period })
12061
+ ]
12062
+ },
12063
+ invoice.id
12064
+ );
12065
+ }) })
12066
+ ] }) }),
12067
+ selectedInvoice && /* @__PURE__ */ jsx155(
12068
+ InvoiceDetails,
12069
+ {
12070
+ invoice: selectedInvoice,
12071
+ open: !!selectedInvoice,
12072
+ onOpenChange: (open) => !open && setSelectedInvoice(null),
12073
+ onInvoiceChange: () => {
12074
+ onInvoicesChange();
12075
+ setSelectedInvoice(null);
12076
+ }
12077
+ }
12078
+ )
12079
+ ] });
12080
+ }
12081
+ __name(InvoicesList, "InvoicesList");
12082
+
12083
+ // src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx
12084
+ import { jsx as jsx156, jsxs as jsxs96 } from "react/jsx-runtime";
12085
+ function InvoicesContainer() {
12086
+ const [invoices, setInvoices] = useState54([]);
12087
+ const [loading, setLoading] = useState54(true);
12088
+ const [statusFilter, setStatusFilter] = useState54("all");
12089
+ const loadInvoices = /* @__PURE__ */ __name(async () => {
12090
+ setLoading(true);
12091
+ try {
12092
+ const params = statusFilter !== "all" ? { status: statusFilter } : void 0;
12093
+ const data = await StripeInvoiceService.listInvoices(params);
12094
+ setInvoices(data);
12095
+ } catch (error) {
12096
+ console.error("[InvoicesContainer] Failed to load invoices:", error);
12097
+ setInvoices([]);
12098
+ } finally {
12099
+ setLoading(false);
12100
+ }
12101
+ }, "loadInvoices");
12102
+ useEffect43(() => {
12103
+ loadInvoices();
12104
+ }, [statusFilter]);
12105
+ const handleFilterChange = /* @__PURE__ */ __name((value) => {
12106
+ setStatusFilter(value);
12107
+ }, "handleFilterChange");
12108
+ return /* @__PURE__ */ jsxs96("div", { className: "space-y-4", children: [
12109
+ /* @__PURE__ */ jsx156(Tabs, { value: statusFilter, onValueChange: handleFilterChange, children: /* @__PURE__ */ jsxs96(TabsList, { children: [
12110
+ /* @__PURE__ */ jsx156(TabsTrigger, { value: "all", children: "All" }),
12111
+ /* @__PURE__ */ jsx156(TabsTrigger, { value: "paid" /* PAID */, children: "Paid" }),
12112
+ /* @__PURE__ */ jsx156(TabsTrigger, { value: "open" /* OPEN */, children: "Open" }),
12113
+ /* @__PURE__ */ jsx156(TabsTrigger, { value: "void" /* VOID */, children: "Void" }),
12114
+ /* @__PURE__ */ jsx156(TabsTrigger, { value: "uncollectible" /* UNCOLLECTIBLE */, children: "Uncollectible" })
12115
+ ] }) }),
12116
+ loading && /* @__PURE__ */ jsx156("div", { className: "text-center py-8 text-muted-foreground", children: "Loading invoices..." }),
12117
+ !loading && invoices.length === 0 && /* @__PURE__ */ jsxs96("div", { className: "border border-dashed border-gray-300 rounded-lg p-8 text-center", children: [
12118
+ /* @__PURE__ */ jsx156("p", { className: "text-lg font-medium text-muted-foreground mb-2", children: "No invoices yet" }),
12119
+ /* @__PURE__ */ jsx156("p", { className: "text-sm text-muted-foreground", children: "Invoices will appear here after your first billing cycle" })
12120
+ ] }),
12121
+ !loading && invoices.length > 0 && /* @__PURE__ */ jsx156(InvoicesList, { invoices, onInvoicesChange: loadInvoices })
12122
+ ] });
12123
+ }
12124
+ __name(InvoicesContainer, "InvoicesContainer");
12125
+
12126
+ // src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx
12127
+ import { CheckCircle as CheckCircle2, CreditCard as CreditCard3, Loader2 as Loader23 } from "lucide-react";
12128
+ import { useEffect as useEffect45, useState as useState60 } from "react";
12129
+ import { v4 as v46 } from "uuid";
12130
+
12131
+ // src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts
12132
+ import { useStripe as useStripe2 } from "@stripe/react-stripe-js";
12133
+ import { useCallback as useCallback17, useState as useState55 } from "react";
12134
+ function useConfirmSubscriptionPayment() {
12135
+ const stripe = useStripe2();
12136
+ const [isConfirming, setIsConfirming] = useState55(false);
12137
+ const confirmPayment = useCallback17(
12138
+ async (clientSecret) => {
12139
+ if (!stripe) {
12140
+ console.error("[useConfirmSubscriptionPayment] Stripe not initialized");
12141
+ return {
12142
+ success: false,
12143
+ error: "Payment system not initialized. Please refresh the page and try again."
12144
+ };
12145
+ }
12146
+ if (!clientSecret) {
12147
+ console.error("[useConfirmSubscriptionPayment] No client secret provided");
12148
+ return {
12149
+ success: false,
12150
+ error: "Payment confirmation failed. Missing payment details."
12151
+ };
12152
+ }
12153
+ setIsConfirming(true);
12154
+ try {
12155
+ const { error: stripeError, paymentIntent } = await stripe.confirmCardPayment(clientSecret);
12156
+ if (stripeError) {
12157
+ console.error("[useConfirmSubscriptionPayment] Stripe error:", stripeError);
12158
+ return {
12159
+ success: false,
12160
+ error: stripeError.message || "Payment confirmation failed. Please try again."
12161
+ };
12162
+ }
12163
+ if (paymentIntent?.status === "succeeded") {
12164
+ return { success: true };
12165
+ }
12166
+ if (paymentIntent?.status === "requires_action") {
12167
+ return {
12168
+ success: false,
12169
+ error: "Additional authentication required. Please complete the verification."
12170
+ };
12171
+ }
12172
+ return {
12173
+ success: false,
12174
+ error: "Payment could not be completed. Please try again."
12175
+ };
12176
+ } catch (err) {
12177
+ console.error("[useConfirmSubscriptionPayment] Unexpected error:", err);
12178
+ return {
12179
+ success: false,
12180
+ error: err.message || "An unexpected error occurred during payment confirmation."
12181
+ };
12182
+ } finally {
12183
+ setIsConfirming(false);
12184
+ }
12185
+ },
12186
+ [stripe]
12187
+ );
12188
+ return {
12189
+ confirmPayment,
12190
+ isConfirming
12191
+ };
12192
+ }
12193
+ __name(useConfirmSubscriptionPayment, "useConfirmSubscriptionPayment");
12194
+
12195
+ // src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx
12196
+ import { zodResolver as zodResolver10 } from "@hookform/resolvers/zod";
12197
+ import { useState as useState56 } from "react";
12198
+ import { useForm as useForm10 } from "react-hook-form";
12199
+ import { z as z10 } from "zod";
12200
+ import { jsx as jsx157, jsxs as jsxs97 } from "react/jsx-runtime";
12201
+ var formSchema = z10.object({
12202
+ cancelImmediately: z10.boolean(),
12203
+ reason: z10.string().optional()
12204
+ });
12205
+ function CancelSubscriptionDialog({
12206
+ subscription,
12207
+ open,
12208
+ onOpenChange,
12209
+ onSuccess
12210
+ }) {
12211
+ const [isSubmitting, setIsSubmitting] = useState56(false);
12212
+ const form = useForm10({
12213
+ resolver: zodResolver10(formSchema),
12214
+ defaultValues: {
12215
+ cancelImmediately: false,
12216
+ reason: ""
12217
+ }
12218
+ });
12219
+ const cancelImmediately = form.watch("cancelImmediately");
12220
+ const onSubmit = /* @__PURE__ */ __name(async (values) => {
12221
+ setIsSubmitting(true);
12222
+ try {
12223
+ await StripeSubscriptionService.cancelSubscription({
12224
+ id: subscription.id,
12225
+ cancelImmediately: values.cancelImmediately
12226
+ });
12227
+ onSuccess();
12228
+ onOpenChange(false);
12229
+ } catch (error) {
12230
+ console.error("[CancelSubscriptionDialog] Failed to cancel subscription:", error);
12231
+ } finally {
12232
+ setIsSubmitting(false);
12233
+ }
12234
+ }, "onSubmit");
12235
+ const periodEndDate = formatDate3(subscription.currentPeriodEnd);
12236
+ return /* @__PURE__ */ jsx157(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs97(DialogContent, { className: "max-w-md", children: [
12237
+ /* @__PURE__ */ jsxs97(DialogHeader, { children: [
12238
+ /* @__PURE__ */ jsx157(DialogTitle, { children: "Cancel Subscription" }),
12239
+ /* @__PURE__ */ jsx157(DialogDescription, { children: "Are you sure you want to cancel this subscription? This action cannot be undone." })
12240
+ ] }),
12241
+ /* @__PURE__ */ jsx157(Form, { ...form, children: /* @__PURE__ */ jsxs97("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
12242
+ /* @__PURE__ */ jsx157(FormCheckbox, { form, id: "cancelImmediately", name: "Cancel Immediately" }),
12243
+ cancelImmediately ? /* @__PURE__ */ jsx157("div", { className: "bg-red-50 border border-red-200 rounded-lg p-3 text-sm text-red-800", children: "Your subscription will be canceled immediately and you will lose access right away." }) : /* @__PURE__ */ jsxs97("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-3 text-sm text-blue-800", children: [
12244
+ "Your subscription will remain active until ",
12245
+ periodEndDate,
12246
+ ". You can continue using the service until then."
12247
+ ] }),
12248
+ /* @__PURE__ */ jsx157(
12249
+ FormTextarea,
12250
+ {
12251
+ form,
12252
+ id: "reason",
12253
+ name: "Reason (Optional)",
12254
+ placeholder: "Let us know why you're canceling...",
12255
+ className: "min-h-24"
12256
+ }
12257
+ ),
12258
+ /* @__PURE__ */ jsxs97("div", { className: "flex gap-x-2 justify-end pt-2", children: [
12259
+ /* @__PURE__ */ jsx157(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), disabled: isSubmitting, children: "Keep Subscription" }),
12260
+ /* @__PURE__ */ jsx157(Button, { type: "submit", variant: "destructive", disabled: isSubmitting, children: isSubmitting ? "Canceling..." : "Confirm Cancellation" })
12261
+ ] })
12262
+ ] }) })
12263
+ ] }) });
12264
+ }
12265
+ __name(CancelSubscriptionDialog, "CancelSubscriptionDialog");
12266
+
12267
+ // src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx
12268
+ import { CheckCircle, Loader2 as Loader22 } from "lucide-react";
12269
+ import { useEffect as useEffect44, useState as useState57 } from "react";
12270
+ import { v4 as v45 } from "uuid";
12271
+
12272
+ // src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx
12273
+ import { Check } from "lucide-react";
12274
+ import { jsx as jsx158, jsxs as jsxs98 } from "react/jsx-runtime";
12275
+ function PricingCard({ price, isCurrentPlan = false, isSelected = false, isDisabled = false, isLoading = false, onSelect }) {
12276
+ const description = price.description || price.nickname || "Standard";
12277
+ const features = price.features || [];
12278
+ const formattedPrice = formatCurrency(price.unitAmount, price.currency);
12279
+ const interval = formatInterval(price);
12280
+ const handleKeyDown = /* @__PURE__ */ __name((e) => {
12281
+ if ((e.key === "Enter" || e.key === " ") && !isDisabled && !isCurrentPlan) {
12282
+ e.preventDefault();
12283
+ onSelect(price);
12284
+ }
12285
+ }, "handleKeyDown");
12286
+ const handleClick = /* @__PURE__ */ __name(() => {
12287
+ if (!isDisabled && !isCurrentPlan && !isLoading) {
12288
+ onSelect(price);
12289
+ }
12290
+ }, "handleClick");
12291
+ return /* @__PURE__ */ jsxs98(
12292
+ Card,
12293
+ {
12294
+ role: "radio",
12295
+ "aria-checked": isSelected,
12296
+ "aria-label": `${description} plan at ${formattedPrice} ${interval}`,
12297
+ tabIndex: isDisabled ? -1 : 0,
12298
+ onKeyDown: handleKeyDown,
12299
+ onClick: handleClick,
12300
+ className: cn(
12301
+ "relative cursor-pointer transition-all duration-200 flex flex-col h-full",
12302
+ "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
12303
+ isCurrentPlan && "bg-muted/30",
12304
+ isSelected && !isCurrentPlan && "ring-2 ring-primary",
12305
+ !isDisabled && !isCurrentPlan && "hover:shadow-md hover:border-primary/50",
12306
+ isDisabled && "opacity-50 pointer-events-none",
12307
+ isLoading && "pointer-events-none"
12308
+ ),
12309
+ children: [
12310
+ isCurrentPlan && /* @__PURE__ */ jsx158(Badge, { variant: "secondary", className: "absolute top-2 right-2", children: "Current" }),
12311
+ /* @__PURE__ */ jsx158(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx158("h3", { className: "font-semibold text-lg", children: description }) }),
12312
+ /* @__PURE__ */ jsxs98(CardContent, { className: "pb-4 grow", children: [
12313
+ /* @__PURE__ */ jsxs98("div", { className: "mb-4", children: [
12314
+ /* @__PURE__ */ jsx158("span", { className: "text-3xl font-bold", children: formattedPrice }),
12315
+ /* @__PURE__ */ jsx158("span", { className: "text-muted-foreground ml-1", children: interval })
12316
+ ] }),
12317
+ features.length > 0 && /* @__PURE__ */ jsx158("ul", { className: "space-y-2", children: features.map((feature, index) => /* @__PURE__ */ jsxs98("li", { className: "flex items-start gap-2", children: [
12318
+ /* @__PURE__ */ jsx158(Check, { className: "h-4 w-4 text-green-500 mt-0.5 shrink-0" }),
12319
+ /* @__PURE__ */ jsx158("span", { className: "text-sm text-muted-foreground", children: feature })
12320
+ ] }, index)) })
12321
+ ] }),
12322
+ /* @__PURE__ */ jsx158(CardFooter, { children: /* @__PURE__ */ jsx158(
12323
+ Button,
12324
+ {
12325
+ variant: isCurrentPlan ? "secondary" : isSelected ? "default" : "outline",
12326
+ className: "w-full",
12327
+ disabled: isDisabled || isCurrentPlan || isLoading,
12328
+ children: isLoading ? "Processing..." : isCurrentPlan ? "Current Plan" : isSelected ? "Selected" : "Select Plan"
12329
+ }
12330
+ ) })
12331
+ ]
12332
+ }
12333
+ );
12334
+ }
12335
+ __name(PricingCard, "PricingCard");
12336
+
12337
+ // src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx
12338
+ import { jsx as jsx159, jsxs as jsxs99 } from "react/jsx-runtime";
12339
+ function PricingCardsGrid({
12340
+ products,
12341
+ pricesByProduct,
12342
+ currentPriceId,
12343
+ selectedPriceId,
12344
+ loadingPriceId,
12345
+ loading = false,
12346
+ onSelectPrice
12347
+ }) {
12348
+ if (loading) {
12349
+ return /* @__PURE__ */ jsx159(PricingCardsGridSkeleton, {});
12350
+ }
12351
+ if (products.length === 0) {
12352
+ return /* @__PURE__ */ jsx159("div", { className: "text-center py-8 text-muted-foreground", children: "No plans available" });
12353
+ }
12354
+ return /* @__PURE__ */ jsx159("div", { className: "space-y-8", role: "radiogroup", "aria-label": "Available pricing plans", children: products.map((product) => {
12355
+ const prices = pricesByProduct.get(product.id) || [];
12356
+ if (prices.length === 0) return null;
12357
+ const sortedPrices = [...prices].sort((a, b) => (a.unitAmount ?? 0) - (b.unitAmount ?? 0));
12358
+ return /* @__PURE__ */ jsxs99("div", { className: "space-y-4", children: [
12359
+ /* @__PURE__ */ jsx159("h3", { className: "text-lg font-semibold", children: product.name }),
12360
+ /* @__PURE__ */ jsx159("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: sortedPrices.map((price) => /* @__PURE__ */ jsx159(
12361
+ PricingCard,
12362
+ {
12363
+ price,
12364
+ isCurrentPlan: price.stripePriceId === currentPriceId,
12365
+ isSelected: price.stripePriceId === selectedPriceId,
12366
+ isLoading: price.stripePriceId === loadingPriceId,
12367
+ onSelect: onSelectPrice
12368
+ },
12369
+ price.stripePriceId
12370
+ )) })
12371
+ ] }, product.id);
12372
+ }) });
12373
+ }
12374
+ __name(PricingCardsGrid, "PricingCardsGrid");
12375
+ function PricingCardsGridSkeleton() {
12376
+ return /* @__PURE__ */ jsx159("div", { className: "space-y-8", children: [1, 2].map((productIndex) => /* @__PURE__ */ jsxs99("div", { className: "space-y-4", children: [
12377
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-6 w-32" }),
12378
+ /* @__PURE__ */ jsx159("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [1, 2, 3].map((cardIndex) => /* @__PURE__ */ jsxs99(Card, { className: "animate-pulse", children: [
12379
+ /* @__PURE__ */ jsx159(CardHeader, { className: "pb-2", children: /* @__PURE__ */ jsx159(Skeleton, { className: "h-5 w-24" }) }),
12380
+ /* @__PURE__ */ jsxs99(CardContent, { className: "pb-4", children: [
12381
+ /* @__PURE__ */ jsxs99("div", { className: "mb-4", children: [
12382
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-9 w-20 inline-block" }),
12383
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-4 w-12 inline-block ml-2" })
12384
+ ] }),
12385
+ /* @__PURE__ */ jsxs99("div", { className: "space-y-2", children: [
12386
+ /* @__PURE__ */ jsxs99("div", { className: "flex items-center gap-2", children: [
12387
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-4 w-4 rounded-full" }),
12388
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-4 w-32" })
12389
+ ] }),
12390
+ /* @__PURE__ */ jsxs99("div", { className: "flex items-center gap-2", children: [
12391
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-4 w-4 rounded-full" }),
12392
+ /* @__PURE__ */ jsx159(Skeleton, { className: "h-4 w-28" })
12393
+ ] })
12394
+ ] })
12395
+ ] }),
12396
+ /* @__PURE__ */ jsx159(CardFooter, { children: /* @__PURE__ */ jsx159(Skeleton, { className: "h-9 w-full" }) })
12397
+ ] }, cardIndex)) })
12398
+ ] }, productIndex)) });
12399
+ }
12400
+ __name(PricingCardsGridSkeleton, "PricingCardsGridSkeleton");
12401
+
12402
+ // src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx
12403
+ import { jsx as jsx160, jsxs as jsxs100 } from "react/jsx-runtime";
12404
+ function ProrationPreview({ preview }) {
12405
+ return /* @__PURE__ */ jsxs100("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4", children: [
12406
+ /* @__PURE__ */ jsx160("h4", { className: "font-semibold text-blue-900 mb-3", children: "Proration Breakdown" }),
12407
+ /* @__PURE__ */ jsxs100("div", { className: "space-y-2", children: [
12408
+ preview.lineItems.map((item, index) => /* @__PURE__ */ jsxs100("div", { className: "flex justify-between text-sm", children: [
12409
+ /* @__PURE__ */ jsx160("span", { className: "text-blue-800", children: item.description }),
12410
+ /* @__PURE__ */ jsx160("span", { className: `font-medium ${item.amount < 0 ? "text-green-600" : "text-blue-900"}`, children: formatCurrency(item.amount, preview.currency) })
12411
+ ] }, index)),
12412
+ /* @__PURE__ */ jsx160("div", { className: "border-t border-blue-200 pt-2 mt-2", children: /* @__PURE__ */ jsxs100("div", { className: "flex justify-between font-semibold", children: [
12413
+ /* @__PURE__ */ jsx160("span", { className: "text-blue-900", children: "Net Due Today" }),
12414
+ /* @__PURE__ */ jsx160("span", { className: "text-blue-900", children: formatCurrency(preview.immediateCharge, preview.currency) })
12415
+ ] }) }),
12416
+ preview.lineItems.length > 0 && preview.lineItems[0].period && /* @__PURE__ */ jsxs100("div", { className: "text-xs text-blue-700 mt-2", children: [
12417
+ "Next invoice on ",
12418
+ formatDate3(preview.lineItems[0].period.end),
12419
+ " for",
12420
+ " ",
12421
+ formatCurrency(preview.amountDue, preview.currency)
12422
+ ] })
12423
+ ] })
12424
+ ] });
12425
+ }
12426
+ __name(ProrationPreview, "ProrationPreview");
12427
+
12428
+ // src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx
12429
+ import { jsx as jsx161, jsxs as jsxs101 } from "react/jsx-runtime";
12430
+ function SubscriptionEditor({
12431
+ subscription,
12432
+ open,
12433
+ onOpenChange,
12434
+ onSuccess,
12435
+ onAddPaymentMethod
12436
+ }) {
12437
+ const { confirmPayment, isConfirming } = useConfirmSubscriptionPayment();
12438
+ const [products, setProducts] = useState57([]);
12439
+ const [pricesByProduct, setPricesByProduct] = useState57(/* @__PURE__ */ new Map());
12440
+ const [loading, setLoading] = useState57(true);
12441
+ const [selectedPriceId, setSelectedPriceId] = useState57(null);
12442
+ const [loadingPriceId, setLoadingPriceId] = useState57(null);
12443
+ const [prorationPreview, setProrationPreview] = useState57(null);
12444
+ const [loadingProration, setLoadingProration] = useState57(false);
12445
+ const [hasPaymentMethod, setHasPaymentMethod] = useState57(true);
12446
+ const [loadingPaymentMethods, setLoadingPaymentMethods] = useState57(true);
12447
+ const [paymentRequiredError, setPaymentRequiredError] = useState57(false);
12448
+ const [paymentConfirmationState, setPaymentConfirmationState] = useState57("idle");
12449
+ const [paymentError, setPaymentError] = useState57(null);
12450
+ const currentPriceId = subscription?.price?.id;
12451
+ const isEditMode = !!subscription;
12452
+ useEffect44(() => {
12453
+ const checkPaymentMethods = /* @__PURE__ */ __name(async () => {
12454
+ if (subscription) {
12455
+ setLoadingPaymentMethods(false);
12456
+ return;
12457
+ }
12458
+ setLoadingPaymentMethods(true);
12459
+ try {
12460
+ const paymentMethods = await StripeCustomerService.listPaymentMethods();
12461
+ const hasMethod = paymentMethods.length > 0;
12462
+ setHasPaymentMethod(hasMethod);
12463
+ } catch (error) {
12464
+ console.error("[SubscriptionEditor] Failed to check payment methods:", error);
12465
+ setHasPaymentMethod(false);
12466
+ } finally {
12467
+ setLoadingPaymentMethods(false);
12468
+ }
12469
+ }, "checkPaymentMethods");
12470
+ if (open) {
12471
+ checkPaymentMethods();
12472
+ }
12473
+ }, [open, subscription]);
12474
+ useEffect44(() => {
12475
+ const loadData = /* @__PURE__ */ __name(async () => {
12476
+ setLoading(true);
12477
+ try {
12478
+ const fetchedProducts = await StripeProductService.listProducts({ active: true });
12479
+ const grouped = /* @__PURE__ */ new Map();
12480
+ for (const product of fetchedProducts) {
12481
+ if (product.stripePrices && product.stripePrices.length > 0) {
12482
+ grouped.set(product.id, product.stripePrices);
12483
+ }
12484
+ }
12485
+ setProducts(fetchedProducts);
12486
+ setPricesByProduct(grouped);
12487
+ } catch (error) {
12488
+ console.error("[SubscriptionEditor] Failed to load products/prices:", error);
12489
+ } finally {
12490
+ setLoading(false);
12491
+ }
12492
+ }, "loadData");
12493
+ if (open) {
12494
+ loadData();
12495
+ }
12496
+ }, [open]);
12497
+ useEffect44(() => {
12498
+ const loadProration = /* @__PURE__ */ __name(async () => {
12499
+ if (!subscription || !selectedPriceId || selectedPriceId === currentPriceId) {
12500
+ setProrationPreview(null);
12501
+ return;
12502
+ }
12503
+ setLoadingProration(true);
12504
+ try {
12505
+ const preview = await StripeSubscriptionService.getProrationPreview({
12506
+ subscriptionId: subscription.id,
12507
+ newPriceId: selectedPriceId
12508
+ });
12509
+ setProrationPreview(preview);
12510
+ } catch (error) {
12511
+ console.error("[SubscriptionEditor] Failed to load proration preview:", error);
12512
+ setProrationPreview(null);
12513
+ } finally {
12514
+ setLoadingProration(false);
12515
+ }
12516
+ }, "loadProration");
12517
+ loadProration();
12518
+ }, [selectedPriceId, subscription, currentPriceId]);
12519
+ const handleSelectPrice = /* @__PURE__ */ __name(async (price) => {
12520
+ const priceId = price.id;
12521
+ if (isEditMode) {
12522
+ setSelectedPriceId(priceId);
12523
+ } else {
12524
+ setLoadingPriceId(priceId);
12525
+ setSelectedPriceId(priceId);
12526
+ setPaymentError(null);
12527
+ setPaymentConfirmationState("idle");
12528
+ try {
12529
+ const result = await StripeSubscriptionService.createSubscription({
12530
+ id: v45(),
12531
+ priceId
12532
+ });
12533
+ if (result.meta.requiresAction && result.meta.clientSecret) {
12534
+ setPaymentConfirmationState("confirming");
12535
+ const confirmation = await confirmPayment(result.meta.clientSecret);
12536
+ if (!confirmation.success) {
12537
+ console.error("[SubscriptionEditor] Payment confirmation failed:", confirmation.error);
12538
+ setPaymentConfirmationState("error");
12539
+ setPaymentError(confirmation.error || "Payment confirmation failed");
12540
+ setLoadingPriceId(null);
12541
+ return;
12542
+ }
12543
+ await StripeSubscriptionService.syncSubscription({
12544
+ subscriptionId: result.subscription.id
12545
+ });
12546
+ }
12547
+ setPaymentConfirmationState("success");
12548
+ setTimeout(() => {
12549
+ onSuccess();
12550
+ onOpenChange(false);
12551
+ }, 1e3);
12552
+ } catch (error) {
12553
+ console.error("[SubscriptionEditor] Failed to create subscription:", error);
12554
+ if (error?.status === 402 || error?.response?.status === 402) {
12555
+ setPaymentRequiredError(true);
12556
+ setHasPaymentMethod(false);
12557
+ } else {
12558
+ setPaymentConfirmationState("error");
12559
+ setPaymentError(error?.message || "Failed to create subscription");
12560
+ }
12561
+ setLoadingPriceId(null);
12562
+ }
12563
+ }
12564
+ }, "handleSelectPrice");
12565
+ const handleConfirmPlanChange = /* @__PURE__ */ __name(async () => {
12566
+ if (!subscription || !selectedPriceId) return;
12567
+ setLoadingPriceId(selectedPriceId);
12568
+ try {
12569
+ await StripeSubscriptionService.changePlan({
12570
+ id: subscription.id,
12571
+ newPriceId: selectedPriceId
12572
+ });
12573
+ onSuccess();
12574
+ onOpenChange(false);
12575
+ } catch (error) {
12576
+ console.error("[SubscriptionEditor] Failed to change plan:", error);
12577
+ } finally {
12578
+ setLoadingPriceId(null);
12579
+ }
12580
+ }, "handleConfirmPlanChange");
12581
+ const handleCancel = /* @__PURE__ */ __name(() => {
12582
+ setSelectedPriceId(null);
12583
+ setProrationPreview(null);
12584
+ }, "handleCancel");
12585
+ return /* @__PURE__ */ jsx161(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs101(DialogContent, { className: "max-w-4xl max-h-[90vh] overflow-y-auto", children: [
12586
+ /* @__PURE__ */ jsxs101(DialogHeader, { children: [
12587
+ /* @__PURE__ */ jsx161(DialogTitle, { children: subscription ? "Change Plan" : "Subscribe to a Plan" }),
12588
+ /* @__PURE__ */ jsx161(DialogDescription, { children: subscription ? "Select a new plan to switch to. You'll see a proration preview before confirming." : "Choose a plan to start your subscription." })
12589
+ ] }),
12590
+ loadingPaymentMethods && !subscription ? /* @__PURE__ */ jsx161("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx161("div", { className: "text-muted-foreground", children: "Checking payment methods..." }) }) : !hasPaymentMethod && !subscription ? /* @__PURE__ */ jsxs101(Alert, { variant: "destructive", children: [
12591
+ /* @__PURE__ */ jsx161(AlertTitle, { children: "Payment Method Required" }),
12592
+ /* @__PURE__ */ jsxs101(AlertDescription, { className: "mt-2", children: [
12593
+ /* @__PURE__ */ jsx161("p", { className: "mb-4", children: paymentRequiredError ? "Your subscription could not be created because no payment method is on file." : "You need to add a payment method before you can subscribe to a plan." }),
12594
+ onAddPaymentMethod && /* @__PURE__ */ jsx161(Button, { onClick: onAddPaymentMethod, variant: "outline", children: "Add Payment Method" })
12595
+ ] })
12596
+ ] }) : paymentConfirmationState === "confirming" || isConfirming ? /* @__PURE__ */ jsxs101("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
12597
+ /* @__PURE__ */ jsx161(Loader22, { className: "h-8 w-8 animate-spin text-primary" }),
12598
+ /* @__PURE__ */ jsxs101("div", { className: "text-center", children: [
12599
+ /* @__PURE__ */ jsx161("p", { className: "font-medium", children: "Processing payment..." }),
12600
+ /* @__PURE__ */ jsx161("p", { className: "text-sm text-muted-foreground", children: "Please complete any verification if prompted." })
12601
+ ] })
12602
+ ] }) : paymentConfirmationState === "success" ? /* @__PURE__ */ jsxs101("div", { className: "flex flex-col items-center justify-center py-12 space-y-4", children: [
12603
+ /* @__PURE__ */ jsx161(CheckCircle, { className: "h-12 w-12 text-green-500" }),
12604
+ /* @__PURE__ */ jsxs101("div", { className: "text-center", children: [
12605
+ /* @__PURE__ */ jsx161("p", { className: "font-medium text-green-600", children: "Payment successful!" }),
12606
+ /* @__PURE__ */ jsx161("p", { className: "text-sm text-muted-foreground", children: "Your subscription is now active." })
12607
+ ] })
12608
+ ] }) : paymentConfirmationState === "error" ? /* @__PURE__ */ jsx161("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs101(Alert, { variant: "destructive", children: [
12609
+ /* @__PURE__ */ jsx161(AlertTitle, { children: "Payment Failed" }),
12610
+ /* @__PURE__ */ jsxs101(AlertDescription, { className: "mt-2", children: [
12611
+ /* @__PURE__ */ jsx161("p", { className: "mb-4", children: paymentError || "We couldn't process your payment. Please try again." }),
12612
+ /* @__PURE__ */ jsx161(
12613
+ Button,
12614
+ {
12615
+ onClick: () => {
12616
+ setPaymentConfirmationState("idle");
12617
+ setPaymentError(null);
12618
+ setLoadingPriceId(null);
12619
+ },
12620
+ variant: "outline",
12621
+ children: "Try Again"
12622
+ }
12623
+ )
12624
+ ] })
12625
+ ] }) }) : /* @__PURE__ */ jsxs101("div", { className: "space-y-6", children: [
12626
+ /* @__PURE__ */ jsx161(
12627
+ PricingCardsGrid,
12628
+ {
12629
+ products,
12630
+ pricesByProduct,
12631
+ currentPriceId,
12632
+ selectedPriceId: selectedPriceId ?? void 0,
12633
+ loadingPriceId: loadingPriceId ?? void 0,
12634
+ loading,
12635
+ onSelectPrice: handleSelectPrice
12636
+ }
12637
+ ),
12638
+ isEditMode && loadingProration && /* @__PURE__ */ jsx161("div", { className: "bg-muted/50 rounded-lg p-4 text-sm text-muted-foreground text-center", children: "Loading proration preview..." }),
12639
+ isEditMode && prorationPreview && !loadingProration && /* @__PURE__ */ jsxs101("div", { className: "space-y-4", children: [
12640
+ /* @__PURE__ */ jsx161(ProrationPreview, { preview: prorationPreview }),
12641
+ /* @__PURE__ */ jsxs101("div", { className: "flex justify-end gap-3", children: [
12642
+ /* @__PURE__ */ jsx161(Button, { variant: "outline", onClick: handleCancel, disabled: !!loadingPriceId, children: "Cancel" }),
12643
+ /* @__PURE__ */ jsx161(Button, { onClick: handleConfirmPlanChange, disabled: !!loadingPriceId, children: loadingPriceId ? "Processing..." : "Confirm Plan Change" })
12644
+ ] })
12645
+ ] })
12646
+ ] })
12647
+ ] }) });
12648
+ }
12649
+ __name(SubscriptionEditor, "SubscriptionEditor");
12650
+
12651
+ // src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx
12652
+ import { useState as useState59 } from "react";
12653
+
12654
+ // src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx
12655
+ import { useState as useState58 } from "react";
12656
+
12657
+ // src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx
12658
+ import { jsx as jsx162 } from "react/jsx-runtime";
12659
+ var statusConfig2 = {
12660
+ ["active" /* ACTIVE */]: {
12661
+ label: "Active",
12662
+ color: "bg-green-100 text-green-800"
12663
+ },
12664
+ ["trialing" /* TRIALING */]: {
12665
+ label: "Trial",
12666
+ color: "bg-blue-100 text-blue-800"
12667
+ },
12668
+ ["past_due" /* PAST_DUE */]: {
12669
+ label: "Past Due",
12670
+ color: "bg-red-100 text-red-800"
12671
+ },
12672
+ ["canceled" /* CANCELED */]: {
12673
+ label: "Canceled",
12674
+ color: "bg-gray-100 text-gray-800"
12675
+ },
12676
+ ["paused" /* PAUSED */]: {
12677
+ label: "Paused",
12678
+ color: "bg-yellow-100 text-yellow-800"
12679
+ },
12680
+ ["unpaid" /* UNPAID */]: {
12681
+ label: "Unpaid",
12682
+ color: "bg-orange-100 text-orange-800"
12683
+ },
12684
+ ["incomplete" /* INCOMPLETE */]: {
12685
+ label: "Incomplete",
12686
+ color: "bg-gray-100 text-gray-800"
12687
+ },
12688
+ ["incomplete_expired" /* INCOMPLETE_EXPIRED */]: {
12689
+ label: "Expired",
12690
+ color: "bg-gray-100 text-gray-800"
12691
+ }
12692
+ };
12693
+ var cancelingConfig = {
12694
+ label: "Canceling",
12695
+ color: "bg-amber-100 text-amber-800"
12696
+ };
12697
+ function SubscriptionStatusBadge({ status, cancelAtPeriodEnd }) {
12698
+ const config = cancelAtPeriodEnd ? cancelingConfig : statusConfig2[status] || statusConfig2["canceled" /* CANCELED */];
12699
+ return /* @__PURE__ */ jsx162("span", { className: `${config.color} text-xs px-2 py-1 rounded-full font-medium`, children: config.label });
12700
+ }
12701
+ __name(SubscriptionStatusBadge, "SubscriptionStatusBadge");
12702
+
12703
+ // src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx
12704
+ import { Fragment as Fragment30, jsx as jsx163, jsxs as jsxs102 } from "react/jsx-runtime";
12705
+ function formatPlanName2(price) {
12706
+ if (!price) return "N/A";
12707
+ const productName = price.product?.name || "";
12708
+ const nickname = price.nickname || "";
12709
+ let interval = "";
12710
+ if (price.recurring?.interval) {
12711
+ const intervalMap = {
12712
+ day: "Daily",
12713
+ week: "Weekly",
12714
+ month: "Monthly",
12715
+ year: "Yearly"
12716
+ };
12717
+ interval = intervalMap[price.recurring.interval] || price.recurring.interval;
12718
+ }
12719
+ const parts = [productName, nickname].filter(Boolean);
12720
+ const planLabel = parts.join(" - ");
12721
+ return interval ? `${planLabel} (${interval})` : planLabel || "N/A";
12722
+ }
12723
+ __name(formatPlanName2, "formatPlanName");
12724
+ function formatBillingAmount(price) {
12725
+ if (!price?.unitAmount) return "N/A";
12726
+ return formatCurrency(price.unitAmount, price.currency);
12727
+ }
12728
+ __name(formatBillingAmount, "formatBillingAmount");
12729
+ function SubscriptionDetails({
12730
+ subscription,
12731
+ open,
12732
+ onOpenChange,
12733
+ onSubscriptionChange
12734
+ }) {
12735
+ const [showEdit, setShowEdit] = useState58(false);
12736
+ const [showCancel, setShowCancel] = useState58(false);
12737
+ const [isProcessing, setIsProcessing] = useState58(false);
12738
+ const handlePause = /* @__PURE__ */ __name(async () => {
12739
+ setIsProcessing(true);
12740
+ try {
12741
+ await StripeSubscriptionService.pauseSubscription({ subscriptionId: subscription.id });
12742
+ onSubscriptionChange();
12743
+ } catch (error) {
12744
+ console.error("[SubscriptionDetails] Failed to pause subscription:", error);
12745
+ } finally {
12746
+ setIsProcessing(false);
12747
+ }
12748
+ }, "handlePause");
12749
+ const handleResume = /* @__PURE__ */ __name(async () => {
12750
+ setIsProcessing(true);
12751
+ try {
12752
+ await StripeSubscriptionService.resumeSubscription({ subscriptionId: subscription.id });
12753
+ onSubscriptionChange();
12754
+ } catch (error) {
12755
+ console.error("[SubscriptionDetails] Failed to resume subscription:", error);
12756
+ } finally {
12757
+ setIsProcessing(false);
12758
+ }
12759
+ }, "handleResume");
12760
+ const handleManageViaPortal = /* @__PURE__ */ __name(async () => {
12761
+ try {
12762
+ const { url } = await StripeCustomerService.createPortalSession();
12763
+ window.open(url, "_blank");
12764
+ } catch (error) {
12765
+ console.error("[SubscriptionDetails] Failed to create portal session:", error);
12766
+ }
12767
+ }, "handleManageViaPortal");
12768
+ const canPause = subscription.status === "active" /* ACTIVE */;
12769
+ const canResume = subscription.status === "paused" /* PAUSED */;
12770
+ const canCancel = subscription.status === "active" /* ACTIVE */ || subscription.status === "trialing" /* TRIALING */ || subscription.status === "paused" /* PAUSED */;
12771
+ return /* @__PURE__ */ jsxs102(Fragment30, { children: [
12772
+ /* @__PURE__ */ jsx163(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs102(DialogContent, { className: "max-w-2xl", children: [
12773
+ /* @__PURE__ */ jsxs102(DialogHeader, { children: [
12774
+ /* @__PURE__ */ jsx163(DialogTitle, { children: "Subscription Details" }),
12775
+ /* @__PURE__ */ jsx163(DialogDescription, { children: "View and manage your subscription" })
12776
+ ] }),
12777
+ /* @__PURE__ */ jsxs102("div", { className: "space-y-6", children: [
12778
+ /* @__PURE__ */ jsxs102("div", { className: "flex items-center gap-x-3", children: [
12779
+ /* @__PURE__ */ jsx163("span", { className: "text-sm font-medium text-muted-foreground", children: "Status:" }),
12780
+ /* @__PURE__ */ jsx163(SubscriptionStatusBadge, { status: subscription.status, cancelAtPeriodEnd: subscription.cancelAtPeriodEnd })
12781
+ ] }),
12782
+ /* @__PURE__ */ jsxs102("div", { className: "space-y-2", children: [
12783
+ /* @__PURE__ */ jsxs102("div", { className: "flex justify-between", children: [
12784
+ /* @__PURE__ */ jsx163("span", { className: "text-sm font-medium text-muted-foreground", children: "Plan:" }),
12785
+ /* @__PURE__ */ jsx163("span", { className: "font-medium", children: formatPlanName2(subscription.price) })
12786
+ ] }),
12787
+ /* @__PURE__ */ jsxs102("div", { className: "flex justify-between", children: [
12788
+ /* @__PURE__ */ jsx163("span", { className: "text-sm font-medium text-muted-foreground", children: "Billing Amount:" }),
12789
+ /* @__PURE__ */ jsx163("span", { className: "font-medium", children: formatBillingAmount(subscription.price) })
12790
+ ] })
12791
+ ] }),
12792
+ /* @__PURE__ */ jsx163("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs102("div", { className: "flex justify-between", children: [
12793
+ /* @__PURE__ */ jsx163("span", { className: "text-sm font-medium text-muted-foreground", children: "Current Period:" }),
12794
+ /* @__PURE__ */ jsxs102("span", { className: "font-medium", children: [
12795
+ formatDate3(subscription.currentPeriodStart),
12796
+ " - ",
12797
+ formatDate3(subscription.currentPeriodEnd)
12798
+ ] })
12799
+ ] }) }),
12800
+ subscription.trialEnd && /* @__PURE__ */ jsxs102("div", { className: "flex justify-between", children: [
12801
+ /* @__PURE__ */ jsx163("span", { className: "text-sm font-medium text-muted-foreground", children: "Trial Ends:" }),
12802
+ /* @__PURE__ */ jsx163("span", { className: "font-medium", children: formatDate3(subscription.trialEnd) })
12803
+ ] }),
12804
+ subscription.cancelAtPeriodEnd && /* @__PURE__ */ jsx163("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-3", children: /* @__PURE__ */ jsxs102("p", { className: "text-sm text-yellow-800", children: [
12805
+ "This subscription will be canceled at the end of the current period on",
12806
+ " ",
12807
+ formatDate3(subscription.currentPeriodEnd),
12808
+ "."
12809
+ ] }) }),
12810
+ /* @__PURE__ */ jsxs102("div", { className: "flex flex-wrap gap-2 pt-4 border-t", children: [
12811
+ /* @__PURE__ */ jsx163(Button, { variant: "default", onClick: () => setShowEdit(true), children: "Change Plan" }),
12812
+ canPause && /* @__PURE__ */ jsx163(Button, { variant: "outline", onClick: handlePause, disabled: isProcessing, children: isProcessing ? "Pausing..." : "Pause" }),
12813
+ canResume && /* @__PURE__ */ jsx163(Button, { variant: "outline", onClick: handleResume, disabled: isProcessing, children: isProcessing ? "Resuming..." : "Resume" }),
12814
+ canCancel && /* @__PURE__ */ jsx163(Button, { variant: "destructive", onClick: () => setShowCancel(true), children: "Cancel" }),
12815
+ /* @__PURE__ */ jsx163(Button, { variant: "outline", onClick: handleManageViaPortal, children: "Manage via Portal" })
12816
+ ] })
12817
+ ] })
12818
+ ] }) }),
12819
+ showEdit && /* @__PURE__ */ jsx163(
12820
+ SubscriptionEditor,
12821
+ {
12822
+ subscription,
12823
+ open: showEdit,
12824
+ onOpenChange: setShowEdit,
12825
+ onSuccess: () => {
12826
+ onSubscriptionChange();
12827
+ setShowEdit(false);
12828
+ }
12829
+ }
12830
+ ),
12831
+ showCancel && /* @__PURE__ */ jsx163(
12832
+ CancelSubscriptionDialog,
12833
+ {
12834
+ subscription,
12835
+ open: showCancel,
12836
+ onOpenChange: setShowCancel,
12837
+ onSuccess: () => {
12838
+ onSubscriptionChange();
12839
+ setShowCancel(false);
12840
+ }
12841
+ }
12842
+ )
12843
+ ] });
12844
+ }
12845
+ __name(SubscriptionDetails, "SubscriptionDetails");
12846
+
12847
+ // src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx
12848
+ import { Fragment as Fragment31, jsx as jsx164, jsxs as jsxs103 } from "react/jsx-runtime";
12849
+ function formatPlanName3(price) {
12850
+ if (!price) return "N/A";
12851
+ const productName = price.product?.name || "";
12852
+ const nickname = price.nickname || "";
12853
+ let interval = "";
12854
+ if (price.recurring?.interval) {
12855
+ const intervalMap = {
12856
+ day: "Daily",
12857
+ week: "Weekly",
12858
+ month: "Monthly",
12859
+ year: "Yearly"
12860
+ };
12861
+ interval = intervalMap[price.recurring.interval] || price.recurring.interval;
12862
+ }
12863
+ const parts = [productName, nickname].filter(Boolean);
12864
+ const planLabel = parts.join(" - ");
12865
+ return interval ? `${planLabel} (${interval})` : planLabel || "N/A";
12866
+ }
12867
+ __name(formatPlanName3, "formatPlanName");
12868
+ function SubscriptionsList({ subscriptions, onSubscriptionsChange }) {
12869
+ const [selectedSub, setSelectedSub] = useState59(null);
12870
+ const handleRowClick = /* @__PURE__ */ __name((subscription) => {
12871
+ setSelectedSub(subscription);
12872
+ }, "handleRowClick");
12873
+ return /* @__PURE__ */ jsxs103(Fragment31, { children: [
12874
+ /* @__PURE__ */ jsx164("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsxs103(Table, { children: [
12875
+ /* @__PURE__ */ jsx164(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs103(TableRow, { children: [
12876
+ /* @__PURE__ */ jsx164(TableHead, { children: "Status" }),
12877
+ /* @__PURE__ */ jsx164(TableHead, { children: "Plan" }),
12878
+ /* @__PURE__ */ jsx164(TableHead, { children: "Period" }),
12879
+ /* @__PURE__ */ jsx164(TableHead, { className: "text-right", children: "Amount" })
12880
+ ] }) }),
12881
+ /* @__PURE__ */ jsx164(TableBody, { children: subscriptions.map((subscription) => {
12882
+ const price = subscription.price;
12883
+ const amount = price?.unitAmount ? formatCurrency(price.unitAmount, price.currency) : "N/A";
12884
+ const period = `${formatDate3(subscription.currentPeriodStart)} - ${formatDate3(subscription.currentPeriodEnd)}`;
12885
+ return /* @__PURE__ */ jsxs103(
12886
+ TableRow,
12887
+ {
12888
+ onClick: () => handleRowClick(subscription),
12889
+ className: "cursor-pointer hover:bg-muted/50",
12890
+ children: [
12891
+ /* @__PURE__ */ jsx164(TableCell, { children: /* @__PURE__ */ jsx164(SubscriptionStatusBadge, { status: subscription.status, cancelAtPeriodEnd: subscription.cancelAtPeriodEnd }) }),
12892
+ /* @__PURE__ */ jsx164(TableCell, { className: "font-medium", children: formatPlanName3(price) }),
12893
+ /* @__PURE__ */ jsx164(TableCell, { className: "text-muted-foreground text-sm", children: period }),
12894
+ /* @__PURE__ */ jsx164(TableCell, { className: "text-right font-medium", children: amount })
12895
+ ]
12896
+ },
12897
+ subscription.id
12898
+ );
12899
+ }) })
12900
+ ] }) }),
12901
+ selectedSub && /* @__PURE__ */ jsx164(
12902
+ SubscriptionDetails,
12903
+ {
12904
+ subscription: selectedSub,
12905
+ open: !!selectedSub,
12906
+ onOpenChange: (open) => !open && setSelectedSub(null),
12907
+ onSubscriptionChange: () => {
12908
+ onSubscriptionsChange();
12909
+ setSelectedSub(null);
12910
+ }
12911
+ }
12912
+ )
12913
+ ] });
12914
+ }
12915
+ __name(SubscriptionsList, "SubscriptionsList");
12916
+
12917
+ // src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx
12918
+ import { Fragment as Fragment32, jsx as jsx165, jsxs as jsxs104 } from "react/jsx-runtime";
12919
+ function SubscriptionsContainer() {
12920
+ const { confirmPayment, isConfirming } = useConfirmSubscriptionPayment();
12921
+ const [subscriptions, setSubscriptions] = useState60([]);
12922
+ const [loading, setLoading] = useState60(true);
12923
+ const [showCreateSubscription, setShowCreateSubscription] = useState60(false);
12924
+ const [showPaymentMethodEditor, setShowPaymentMethodEditor] = useState60(false);
12925
+ const [products, setProducts] = useState60([]);
12926
+ const [pricesByProduct, setPricesByProduct] = useState60(/* @__PURE__ */ new Map());
12927
+ const [loadingPricing, setLoadingPricing] = useState60(false);
12928
+ const [hasPaymentMethod, setHasPaymentMethod] = useState60(null);
12929
+ const [pendingPriceId, setPendingPriceId] = useState60(null);
12930
+ const [creatingSubscription, setCreatingSubscription] = useState60(false);
12931
+ const [paymentConfirmationState, setPaymentConfirmationState] = useState60("idle");
12932
+ const [paymentError, setPaymentError] = useState60(null);
12933
+ const loadSubscriptions = /* @__PURE__ */ __name(async () => {
12934
+ setLoading(true);
12935
+ try {
12936
+ const fetchedSubscriptions = await StripeSubscriptionService.listSubscriptions();
12937
+ setSubscriptions(fetchedSubscriptions);
12938
+ } catch (error) {
12939
+ console.error("[SubscriptionsContainer] Failed to load subscriptions:", error);
12940
+ } finally {
12941
+ setLoading(false);
12942
+ }
12943
+ }, "loadSubscriptions");
12944
+ const loadPricingData = /* @__PURE__ */ __name(async () => {
12945
+ setLoadingPricing(true);
12946
+ try {
12947
+ const fetchedProducts = await StripeProductService.listProducts({ active: true });
12948
+ const grouped = /* @__PURE__ */ new Map();
12949
+ for (const product of fetchedProducts) {
12950
+ if (product.stripePrices && product.stripePrices.length > 0) {
12951
+ grouped.set(product.id, product.stripePrices);
12952
+ }
12953
+ }
12954
+ setProducts(fetchedProducts);
12955
+ setPricesByProduct(grouped);
12956
+ } catch (error) {
12957
+ console.error("[SubscriptionsContainer] Failed to load pricing data:", error);
12958
+ } finally {
12959
+ setLoadingPricing(false);
12960
+ }
12961
+ }, "loadPricingData");
12962
+ const checkPaymentMethod = /* @__PURE__ */ __name(async () => {
12963
+ try {
12964
+ const paymentMethods = await StripeCustomerService.listPaymentMethods();
12965
+ const hasMethod = paymentMethods.length > 0;
12966
+ setHasPaymentMethod(hasMethod);
12967
+ } catch (error) {
12968
+ console.error("[SubscriptionsContainer] Failed to check payment methods:", error);
12969
+ setHasPaymentMethod(false);
12970
+ }
12971
+ }, "checkPaymentMethod");
12972
+ const createSubscriptionWithPrice = /* @__PURE__ */ __name(async (priceId) => {
12973
+ setCreatingSubscription(true);
12974
+ setPaymentError(null);
12975
+ setPaymentConfirmationState("idle");
12976
+ try {
12977
+ const result = await StripeSubscriptionService.createSubscription({
12978
+ id: v46(),
12979
+ priceId
12980
+ });
12981
+ if (result.meta.requiresAction && result.meta.clientSecret) {
12982
+ setPaymentConfirmationState("confirming");
12983
+ const confirmation = await confirmPayment(result.meta.clientSecret);
12984
+ if (!confirmation.success) {
12985
+ console.error("[SubscriptionsContainer] Payment confirmation failed:", confirmation.error);
12986
+ setPaymentConfirmationState("error");
12987
+ setPaymentError(confirmation.error || "Payment confirmation failed");
12988
+ setCreatingSubscription(false);
12989
+ return;
12990
+ }
12991
+ await StripeSubscriptionService.syncSubscription({
12992
+ subscriptionId: result.subscription.id
12993
+ });
12994
+ }
12995
+ setPaymentConfirmationState("success");
12996
+ await loadSubscriptions();
12997
+ } catch (error) {
12998
+ console.error("[SubscriptionsContainer] Failed to create subscription:", error);
12999
+ if (error?.status === 402 || error?.response?.status === 402) {
13000
+ setPendingPriceId(priceId);
13001
+ setHasPaymentMethod(false);
13002
+ setShowPaymentMethodEditor(true);
13003
+ } else {
13004
+ setPaymentConfirmationState("error");
13005
+ setPaymentError(error?.message || "Failed to create subscription");
13006
+ }
13007
+ } finally {
13008
+ setCreatingSubscription(false);
13009
+ }
13010
+ }, "createSubscriptionWithPrice");
13011
+ const handleSelectPrice = /* @__PURE__ */ __name(async (price) => {
13012
+ const priceId = price.id;
13013
+ if (!hasPaymentMethod) {
13014
+ setPendingPriceId(priceId);
13015
+ setShowPaymentMethodEditor(true);
13016
+ return;
13017
+ }
13018
+ await createSubscriptionWithPrice(priceId);
13019
+ }, "handleSelectPrice");
13020
+ const handlePaymentMethodSuccess = /* @__PURE__ */ __name(async () => {
13021
+ setShowPaymentMethodEditor(false);
13022
+ setHasPaymentMethod(true);
13023
+ if (pendingPriceId) {
13024
+ await createSubscriptionWithPrice(pendingPriceId);
13025
+ setPendingPriceId(null);
13026
+ }
13027
+ }, "handlePaymentMethodSuccess");
13028
+ useEffect45(() => {
13029
+ loadSubscriptions();
13030
+ }, []);
13031
+ useEffect45(() => {
13032
+ if (!loading && subscriptions.length === 0) {
13033
+ loadPricingData();
13034
+ checkPaymentMethod();
13035
+ }
13036
+ }, [loading, subscriptions.length]);
13037
+ const criticalSubscriptions = subscriptions.filter(
13038
+ (sub) => sub.status === "past_due" /* PAST_DUE */ || sub.status === "trialing" /* TRIALING */ && sub.trialEnd && new Date(sub.trialEnd).getTime() - (/* @__PURE__ */ new Date()).getTime() <= 7 * 24 * 60 * 60 * 1e3
13039
+ );
13040
+ if (loading) {
13041
+ return /* @__PURE__ */ jsx165("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx165("p", { className: "text-muted-foreground", children: "Loading subscriptions..." }) });
13042
+ }
13043
+ return /* @__PURE__ */ jsxs104("div", { className: "flex w-full flex-col gap-y-6", children: [
13044
+ /* @__PURE__ */ jsxs104("div", { className: "flex items-center justify-between", children: [
13045
+ /* @__PURE__ */ jsxs104("div", { className: "flex items-center gap-x-3", children: [
13046
+ /* @__PURE__ */ jsx165(CreditCard3, { className: "h-8 w-8" }),
13047
+ /* @__PURE__ */ jsx165("h1", { className: "text-3xl font-bold", children: "Subscriptions" })
13048
+ ] }),
13049
+ subscriptions.length > 0 && /* @__PURE__ */ jsx165(Button, { onClick: () => setShowCreateSubscription(true), children: "Subscribe to a Plan" })
13050
+ ] }),
13051
+ criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx165(BillingAlertBanner, { subscription }, subscription.id)),
13052
+ subscriptions.length === 0 && /* @__PURE__ */ jsxs104("div", { className: "space-y-6", children: [
13053
+ (paymentConfirmationState === "confirming" || isConfirming) && /* @__PURE__ */ jsxs104("div", { className: "flex flex-col items-center justify-center py-12 space-y-4 bg-muted/50 rounded-lg", children: [
13054
+ /* @__PURE__ */ jsx165(Loader23, { className: "h-8 w-8 animate-spin text-primary" }),
13055
+ /* @__PURE__ */ jsxs104("div", { className: "text-center", children: [
13056
+ /* @__PURE__ */ jsx165("p", { className: "font-medium", children: "Processing payment..." }),
13057
+ /* @__PURE__ */ jsx165("p", { className: "text-sm text-muted-foreground", children: "Please complete any verification if prompted." })
13058
+ ] })
13059
+ ] }),
13060
+ paymentConfirmationState === "success" && /* @__PURE__ */ jsxs104("div", { className: "flex flex-col items-center justify-center py-8 space-y-4 bg-green-50 rounded-lg border border-green-200", children: [
13061
+ /* @__PURE__ */ jsx165(CheckCircle2, { className: "h-12 w-12 text-green-500" }),
13062
+ /* @__PURE__ */ jsxs104("div", { className: "text-center", children: [
13063
+ /* @__PURE__ */ jsx165("p", { className: "font-medium text-green-600", children: "Payment successful!" }),
13064
+ /* @__PURE__ */ jsx165("p", { className: "text-sm text-muted-foreground", children: "Your subscription is now active." })
13065
+ ] })
13066
+ ] }),
13067
+ paymentConfirmationState === "error" && /* @__PURE__ */ jsxs104(Alert, { variant: "destructive", children: [
13068
+ /* @__PURE__ */ jsx165(AlertTitle, { children: "Payment Failed" }),
13069
+ /* @__PURE__ */ jsxs104(AlertDescription, { className: "mt-2", children: [
13070
+ /* @__PURE__ */ jsx165("p", { className: "mb-4", children: paymentError || "We couldn't process your payment. Please try again." }),
13071
+ /* @__PURE__ */ jsx165(
13072
+ Button,
13073
+ {
13074
+ onClick: () => {
13075
+ setPaymentConfirmationState("idle");
13076
+ setPaymentError(null);
13077
+ },
13078
+ variant: "outline",
13079
+ children: "Try Again"
13080
+ }
13081
+ )
13082
+ ] })
13083
+ ] }),
13084
+ paymentConfirmationState === "idle" && !isConfirming && /* @__PURE__ */ jsxs104(Fragment32, { children: [
13085
+ /* @__PURE__ */ jsxs104("div", { className: "text-center", children: [
13086
+ /* @__PURE__ */ jsx165(CreditCard3, { className: "text-muted-foreground mx-auto h-16 w-16 mb-4" }),
13087
+ /* @__PURE__ */ jsx165("h3", { className: "mb-2 text-xl font-semibold", children: "Choose Your Plan" }),
13088
+ /* @__PURE__ */ jsx165("p", { className: "text-muted-foreground mb-6", children: "Select a subscription plan to get started with our services." })
13089
+ ] }),
13090
+ /* @__PURE__ */ jsx165(
13091
+ PricingCardsGrid,
13092
+ {
13093
+ products,
13094
+ pricesByProduct,
13095
+ loading: loadingPricing,
13096
+ loadingPriceId: creatingSubscription ? pendingPriceId ?? void 0 : void 0,
13097
+ onSelectPrice: handleSelectPrice
13098
+ }
13099
+ )
13100
+ ] })
13101
+ ] }),
13102
+ subscriptions.length > 0 && /* @__PURE__ */ jsx165(SubscriptionsList, { subscriptions, onSubscriptionsChange: loadSubscriptions }),
13103
+ showCreateSubscription && /* @__PURE__ */ jsx165(
13104
+ SubscriptionEditor,
13105
+ {
13106
+ open: showCreateSubscription,
13107
+ onOpenChange: setShowCreateSubscription,
13108
+ onSuccess: loadSubscriptions,
13109
+ onAddPaymentMethod: () => {
13110
+ setShowCreateSubscription(false);
13111
+ setShowPaymentMethodEditor(true);
13112
+ }
13113
+ }
13114
+ ),
13115
+ showPaymentMethodEditor && /* @__PURE__ */ jsx165(
13116
+ PaymentMethodEditor,
13117
+ {
13118
+ open: showPaymentMethodEditor,
13119
+ onOpenChange: (open) => {
13120
+ setShowPaymentMethodEditor(open);
13121
+ if (!open) {
13122
+ setPendingPriceId(null);
13123
+ }
13124
+ },
13125
+ onSuccess: handlePaymentMethodSuccess
13126
+ }
13127
+ )
13128
+ ] });
13129
+ }
13130
+ __name(SubscriptionsContainer, "SubscriptionsContainer");
13131
+
13132
+ // src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
13133
+ import { Activity as Activity3 } from "lucide-react";
13134
+ import { useEffect as useEffect46, useState as useState61 } from "react";
13135
+
13136
+ // src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx
13137
+ import { Activity as Activity2 } from "lucide-react";
13138
+ import { jsx as jsx166, jsxs as jsxs105 } from "react/jsx-runtime";
13139
+ function getProgressColor(percentage) {
13140
+ if (percentage === null) return "bg-blue-500";
13141
+ if (percentage >= 90) return "bg-red-500";
13142
+ if (percentage >= 75) return "bg-orange-500";
13143
+ return "bg-green-500";
13144
+ }
13145
+ __name(getProgressColor, "getProgressColor");
13146
+ function formatDate4(date) {
13147
+ if (!date) return "N/A";
13148
+ try {
13149
+ return new Intl.DateTimeFormat("en-US", {
13150
+ month: "short",
13151
+ day: "numeric"
13152
+ }).format(new Date(date));
13153
+ } catch (error) {
13154
+ return "Invalid Date";
13155
+ }
13156
+ }
13157
+ __name(formatDate4, "formatDate");
13158
+ function UsageSummaryCard({ meter, summary }) {
13159
+ const currentUsage = summary?.aggregatedValue ?? 0;
13160
+ const limit = meter.limit;
13161
+ const percentage = limit && limit > 0 ? currentUsage / limit * 100 : null;
13162
+ const progressColor = getProgressColor(percentage);
13163
+ const progressWidth = percentage !== null ? Math.min(percentage, 100) : 0;
13164
+ const displayName = meter.displayName || meter.eventName;
13165
+ const hasLimit = limit !== null && limit !== void 0;
13166
+ return /* @__PURE__ */ jsxs105(Card, { children: [
13167
+ /* @__PURE__ */ jsxs105(CardHeader, { className: "flex flex-row items-center gap-x-3 pb-3", children: [
13168
+ /* @__PURE__ */ jsx166("div", { className: "flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600", children: /* @__PURE__ */ jsx166(Activity2, { className: "h-5 w-5" }) }),
13169
+ /* @__PURE__ */ jsxs105("div", { className: "flex flex-col", children: [
13170
+ /* @__PURE__ */ jsx166("h3", { className: "font-semibold", children: displayName }),
13171
+ /* @__PURE__ */ jsx166("p", { className: "text-xs text-gray-500", children: meter.id })
13172
+ ] })
13173
+ ] }),
13174
+ /* @__PURE__ */ jsxs105(CardContent, { className: "flex flex-col gap-y-4", children: [
13175
+ /* @__PURE__ */ jsxs105("div", { children: [
13176
+ /* @__PURE__ */ jsx166("p", { className: "text-3xl font-bold", children: currentUsage.toLocaleString() }),
13177
+ hasLimit && /* @__PURE__ */ jsxs105("p", { className: "text-sm text-gray-500", children: [
13178
+ "of ",
13179
+ limit.toLocaleString(),
13180
+ " used"
13181
+ ] })
13182
+ ] }),
13183
+ hasLimit ? /* @__PURE__ */ jsxs105("div", { className: "flex flex-col gap-y-2", children: [
13184
+ /* @__PURE__ */ jsx166("div", { className: "h-2 w-full overflow-hidden rounded-full bg-gray-200", children: /* @__PURE__ */ jsx166("div", { className: `h-full transition-all ${progressColor}`, style: { width: `${progressWidth}%` } }) }),
13185
+ /* @__PURE__ */ jsxs105("p", { className: "text-sm text-gray-500", children: [
13186
+ percentage?.toFixed(1),
13187
+ "% used"
13188
+ ] })
13189
+ ] }) : /* @__PURE__ */ jsx166("p", { className: "text-sm text-gray-500", children: "No limit set" }),
13190
+ summary && summary.start && summary.end && /* @__PURE__ */ jsx166("div", { className: "border-t pt-3", children: /* @__PURE__ */ jsxs105("p", { className: "text-xs text-gray-500", children: [
13191
+ "Period: ",
13192
+ formatDate4(summary.start),
13193
+ " - ",
13194
+ formatDate4(summary.end)
13195
+ ] }) })
13196
+ ] })
13197
+ ] });
13198
+ }
13199
+ __name(UsageSummaryCard, "UsageSummaryCard");
13200
+
13201
+ // src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx
13202
+ import { jsx as jsx167 } from "react/jsx-runtime";
13203
+ function UsageSummaryCards({ meters, summaries }) {
13204
+ return /* @__PURE__ */ jsx167("div", { className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3", children: meters.map((meter) => /* @__PURE__ */ jsx167(UsageSummaryCard, { meter, summary: summaries[meter.id] || null }, meter.id)) });
13205
+ }
13206
+ __name(UsageSummaryCards, "UsageSummaryCards");
13207
+
13208
+ // src/features/billing/stripe-usage/components/containers/UsageContainer.tsx
13209
+ import { jsx as jsx168, jsxs as jsxs106 } from "react/jsx-runtime";
13210
+ function UsageContainer() {
13211
+ const [meters, setMeters] = useState61([]);
13212
+ const [summaries, setSummaries] = useState61({});
13213
+ const [loading, setLoading] = useState61(true);
13214
+ const [subscriptions, setSubscriptions] = useState61([]);
13215
+ useEffect46(() => {
13216
+ loadUsageData();
13217
+ }, []);
13218
+ const loadUsageData = /* @__PURE__ */ __name(async () => {
13219
+ setLoading(true);
13220
+ try {
13221
+ const fetchedSubscriptions = await StripeSubscriptionService.listSubscriptions();
13222
+ setSubscriptions(fetchedSubscriptions);
13223
+ const hasMeteredSubscriptions2 = fetchedSubscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
13224
+ if (!hasMeteredSubscriptions2) {
13225
+ setLoading(false);
13226
+ return;
13227
+ }
13228
+ const fetchedMeters = await StripeUsageService.listMeters();
13229
+ setMeters(fetchedMeters);
13230
+ const summariesMap = {};
13231
+ const now = /* @__PURE__ */ new Date();
13232
+ const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
13233
+ const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
13234
+ for (const meter of fetchedMeters) {
13235
+ try {
13236
+ const meterSummaries = await StripeUsageService.getMeterSummaries({
13237
+ meterId: meter.id,
13238
+ startTime: startOfMonth,
13239
+ endTime: endOfMonth
13240
+ });
13241
+ summariesMap[meter.id] = meterSummaries.length > 0 ? meterSummaries[0] : null;
13242
+ } catch (error) {
13243
+ console.error(`[UsageContainer] Failed to load summaries for meter ${meter.id}:`, error);
13244
+ summariesMap[meter.id] = null;
13245
+ }
13246
+ }
13247
+ setSummaries(summariesMap);
13248
+ } catch (error) {
13249
+ console.error("[UsageContainer] Failed to load usage data:", error);
13250
+ } finally {
13251
+ setLoading(false);
13252
+ }
13253
+ }, "loadUsageData");
13254
+ const hasMeteredSubscriptions = subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
13255
+ if (!loading && !hasMeteredSubscriptions) {
13256
+ return null;
13257
+ }
13258
+ if (loading) {
13259
+ return /* @__PURE__ */ jsx168("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx168("p", { className: "text-muted-foreground", children: "Loading usage data..." }) });
13260
+ }
13261
+ return /* @__PURE__ */ jsxs106("div", { className: "flex w-full flex-col gap-y-6", children: [
13262
+ /* @__PURE__ */ jsxs106("div", { className: "flex items-center gap-x-3", children: [
13263
+ /* @__PURE__ */ jsx168(Activity3, { className: "h-8 w-8" }),
13264
+ /* @__PURE__ */ jsx168("h1", { className: "text-3xl font-bold", children: "Usage Tracking" })
13265
+ ] }),
13266
+ meters.length === 0 && /* @__PURE__ */ jsxs106("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed border-gray-300 p-12", children: [
13267
+ /* @__PURE__ */ jsx168(Activity3, { className: "text-muted-foreground h-16 w-16" }),
13268
+ /* @__PURE__ */ jsxs106("div", { className: "text-center", children: [
13269
+ /* @__PURE__ */ jsx168("h3", { className: "mb-2 text-xl font-semibold", children: "No usage meters configured" }),
13270
+ /* @__PURE__ */ jsx168("p", { className: "text-muted-foreground", children: "Usage tracking will appear here when you have metered subscriptions with configured meters." })
13271
+ ] })
13272
+ ] }),
13273
+ meters.length > 0 && /* @__PURE__ */ jsx168(UsageSummaryCards, { meters, summaries })
13274
+ ] });
13275
+ }
13276
+ __name(UsageContainer, "UsageContainer");
13277
+
13278
+ // src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx
13279
+ import { jsx as jsx169, jsxs as jsxs107 } from "react/jsx-runtime";
13280
+ function formatDateTime(date) {
13281
+ if (!date) return "N/A";
13282
+ const dateObj = typeof date === "string" ? new Date(date) : date;
13283
+ try {
13284
+ return new Intl.DateTimeFormat("en-US", {
13285
+ month: "short",
13286
+ day: "numeric",
13287
+ year: "numeric",
13288
+ hour: "numeric",
13289
+ minute: "2-digit"
13290
+ }).format(dateObj);
13291
+ } catch (error) {
13292
+ return "Invalid Date";
13293
+ }
13294
+ }
13295
+ __name(formatDateTime, "formatDateTime");
13296
+ function UsageHistoryTable({ usageRecords }) {
13297
+ if (usageRecords.length === 0) {
13298
+ return /* @__PURE__ */ jsx169("div", { className: "rounded-lg border p-8 text-center", children: /* @__PURE__ */ jsx169("p", { className: "text-muted-foreground", children: "No usage history available." }) });
13299
+ }
13300
+ return /* @__PURE__ */ jsxs107("div", { className: "flex w-full flex-col gap-y-4", children: [
13301
+ /* @__PURE__ */ jsx169("h2", { className: "text-xl font-semibold", children: "Usage History" }),
13302
+ /* @__PURE__ */ jsx169("div", { className: "overflow-hidden rounded-lg border", children: /* @__PURE__ */ jsxs107(Table, { children: [
13303
+ /* @__PURE__ */ jsx169(TableHeader, { className: "bg-muted", children: /* @__PURE__ */ jsxs107(TableRow, { children: [
13304
+ /* @__PURE__ */ jsx169(TableHead, { children: "Date & Time" }),
13305
+ /* @__PURE__ */ jsx169(TableHead, { children: "Meter Event" }),
13306
+ /* @__PURE__ */ jsx169(TableHead, { className: "text-right", children: "Quantity" }),
13307
+ /* @__PURE__ */ jsx169(TableHead, { children: "Event ID" })
13308
+ ] }) }),
13309
+ /* @__PURE__ */ jsx169(TableBody, { children: usageRecords.map((record) => {
13310
+ const dateTime = formatDateTime(record.timestamp);
13311
+ const quantity = record.quantity.toLocaleString();
13312
+ return /* @__PURE__ */ jsxs107(TableRow, { children: [
13313
+ /* @__PURE__ */ jsx169(TableCell, { className: "font-medium", children: dateTime }),
13314
+ /* @__PURE__ */ jsx169(TableCell, { className: "text-muted-foreground", children: record.meterEventName }),
13315
+ /* @__PURE__ */ jsx169(TableCell, { className: "text-right font-medium", children: quantity }),
13316
+ /* @__PURE__ */ jsx169(TableCell, { className: "text-muted-foreground text-sm font-mono", children: record.stripeEventId })
13317
+ ] }, record.id);
13318
+ }) })
13319
+ ] }) })
13320
+ ] });
13321
+ }
13322
+ __name(UsageHistoryTable, "UsageHistoryTable");
13323
+
13324
+ // src/features/billing/components/modals/BillingDetailModal.tsx
13325
+ import { jsx as jsx170, jsxs as jsxs108 } from "react/jsx-runtime";
13326
+ function BillingDetailModal({
13327
+ open,
13328
+ onOpenChange,
13329
+ title,
13330
+ children,
13331
+ className
13332
+ }) {
13333
+ return /* @__PURE__ */ jsx170(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs108(DialogContent, { className: className ?? "max-w-4xl max-h-[90vh] overflow-y-auto", children: [
13334
+ /* @__PURE__ */ jsx170(DialogHeader, { children: /* @__PURE__ */ jsx170(DialogTitle, { children: title }) }),
13335
+ children
13336
+ ] }) });
13337
+ }
13338
+ __name(BillingDetailModal, "BillingDetailModal");
13339
+
13340
+ // src/features/billing/components/widgets/BillingAlertBanner.tsx
13341
+ import { AlertCircle } from "lucide-react";
13342
+ import { jsx as jsx171, jsxs as jsxs109 } from "react/jsx-runtime";
13343
+ function BillingAlertBanner({ subscription, onUpdatePayment, onAddPayment }) {
13344
+ if (subscription.status === "past_due" /* PAST_DUE */) {
13345
+ return /* @__PURE__ */ jsxs109("div", { className: "bg-red-50 border border-red-200 rounded-lg p-4 flex items-start gap-x-3", children: [
13346
+ /* @__PURE__ */ jsx171(AlertCircle, { className: "h-5 w-5 text-red-600 mt-0.5" }),
13347
+ /* @__PURE__ */ jsxs109("div", { className: "flex-1", children: [
13348
+ /* @__PURE__ */ jsx171("h3", { className: "font-semibold text-red-900", children: "Payment Failed" }),
13349
+ /* @__PURE__ */ jsx171("p", { className: "text-sm text-red-700 mt-1", children: "Your last payment failed. Please update your payment method to avoid service interruption." })
13350
+ ] }),
13351
+ onUpdatePayment && /* @__PURE__ */ jsx171(Button, { variant: "outline", size: "sm", onClick: onUpdatePayment, className: "border-red-300 text-red-700", children: "Update Payment Method" })
13352
+ ] });
13353
+ }
13354
+ if (subscription.status === "trialing" /* TRIALING */ && subscription.trialEnd) {
13355
+ const trialEnd = new Date(subscription.trialEnd);
13356
+ const now = /* @__PURE__ */ new Date();
13357
+ const daysRemaining = Math.ceil((trialEnd.getTime() - now.getTime()) / (1e3 * 60 * 60 * 24));
13358
+ if (daysRemaining <= 7) {
13359
+ return /* @__PURE__ */ jsxs109("div", { className: "bg-yellow-50 border border-yellow-200 rounded-lg p-4 flex items-start gap-x-3", children: [
13360
+ /* @__PURE__ */ jsx171(AlertCircle, { className: "h-5 w-5 text-yellow-600 mt-0.5" }),
13361
+ /* @__PURE__ */ jsxs109("div", { className: "flex-1", children: [
13362
+ /* @__PURE__ */ jsx171("h3", { className: "font-semibold text-yellow-900", children: "Trial Ending Soon" }),
13363
+ /* @__PURE__ */ jsxs109("p", { className: "text-sm text-yellow-700 mt-1", children: [
13364
+ "Your trial ends in ",
13365
+ daysRemaining,
13366
+ " ",
13367
+ daysRemaining === 1 ? "day" : "days",
13368
+ ". Add a payment method to continue your subscription."
13369
+ ] })
13370
+ ] }),
13371
+ onAddPayment && /* @__PURE__ */ jsx171(Button, { variant: "outline", size: "sm", onClick: onAddPayment, className: "border-yellow-300 text-yellow-700", children: "Add Payment Method" })
13372
+ ] });
13373
+ }
13374
+ }
13375
+ return null;
13376
+ }
13377
+ __name(BillingAlertBanner, "BillingAlertBanner");
13378
+
13379
+ // src/features/billing/components/containers/BillingDashboardContainer.tsx
13380
+ import { Fragment as Fragment33, jsx as jsx172, jsxs as jsxs110 } from "react/jsx-runtime";
13381
+ function BillingDashboardContainer() {
13382
+ const [data, setData] = useState62({
13383
+ customer: null,
13384
+ subscriptions: [],
13385
+ paymentMethods: [],
13386
+ invoices: [],
13387
+ meters: [],
13388
+ meterSummaries: {}
13389
+ });
13390
+ const [loading, setLoading] = useState62({
13391
+ customer: true,
13392
+ subscriptions: true,
13393
+ paymentMethods: true,
13394
+ invoices: true,
13395
+ usage: true
13396
+ });
13397
+ const [errors, setErrors] = useState62({
13398
+ customer: null,
13399
+ subscriptions: null,
13400
+ paymentMethods: null,
13401
+ invoices: null,
13402
+ usage: null
13403
+ });
13404
+ const [activeModal, setActiveModal] = useState62(null);
13405
+ const [noCustomerExists, setNoCustomerExists] = useState62(false);
13406
+ const [creatingCustomer, setCreatingCustomer] = useState62(false);
13407
+ const hasMeteredSubscriptions = useCallback18(() => {
13408
+ return data.subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
13409
+ }, [data.subscriptions]);
13410
+ const fetchAllData = useCallback18(async () => {
13411
+ setNoCustomerExists(false);
13412
+ let customer = null;
13413
+ try {
13414
+ customer = await StripeCustomerService.getCustomer();
13415
+ setData((prev) => ({ ...prev, customer }));
13416
+ setErrors((prev) => ({ ...prev, customer: null }));
13417
+ setNoCustomerExists(false);
13418
+ } catch (error) {
13419
+ console.error("[BillingDashboard] Failed to load customer:", error);
13420
+ const errorMessage = error instanceof Error ? error.message : String(error);
13421
+ if (errorMessage.includes("Not Found") || errorMessage.includes("not found")) {
13422
+ setNoCustomerExists(true);
13423
+ setLoading({
13424
+ customer: false,
13425
+ subscriptions: false,
13426
+ paymentMethods: false,
13427
+ invoices: false,
13428
+ usage: false
13429
+ });
13430
+ return;
13431
+ }
13432
+ setErrors((prev) => ({ ...prev, customer: "Failed to load billing account" }));
13433
+ } finally {
13434
+ setLoading((prev) => ({ ...prev, customer: false }));
13435
+ }
13436
+ if (customer) {
13437
+ const fetchSubscriptions = /* @__PURE__ */ __name(async () => {
13438
+ try {
13439
+ const subscriptions2 = await StripeSubscriptionService.listSubscriptions();
13440
+ setData((prev) => ({ ...prev, subscriptions: subscriptions2 }));
13441
+ setErrors((prev) => ({ ...prev, subscriptions: null }));
13442
+ return subscriptions2;
13443
+ } catch (error) {
13444
+ console.error("[BillingDashboard] Failed to load subscriptions:", error);
13445
+ setErrors((prev) => ({ ...prev, subscriptions: "Failed to load subscriptions" }));
13446
+ return [];
13447
+ } finally {
13448
+ setLoading((prev) => ({ ...prev, subscriptions: false }));
13449
+ }
13450
+ }, "fetchSubscriptions");
13451
+ const fetchPaymentMethods = /* @__PURE__ */ __name(async () => {
13452
+ try {
13453
+ const paymentMethods = await StripeCustomerService.listPaymentMethods();
13454
+ setData((prev) => ({ ...prev, paymentMethods }));
13455
+ setErrors((prev) => ({ ...prev, paymentMethods: null }));
13456
+ } catch (error) {
13457
+ console.error("[BillingDashboard] Failed to load payment methods:", error);
13458
+ setErrors((prev) => ({ ...prev, paymentMethods: "Failed to load payment methods" }));
13459
+ } finally {
13460
+ setLoading((prev) => ({ ...prev, paymentMethods: false }));
13461
+ }
13462
+ }, "fetchPaymentMethods");
13463
+ const fetchInvoices = /* @__PURE__ */ __name(async () => {
13464
+ try {
13465
+ const invoices = await StripeInvoiceService.listInvoices();
13466
+ setData((prev) => ({ ...prev, invoices }));
13467
+ setErrors((prev) => ({ ...prev, invoices: null }));
13468
+ } catch (error) {
13469
+ console.error("[BillingDashboard] Failed to load invoices:", error);
13470
+ setErrors((prev) => ({ ...prev, invoices: "Failed to load invoices" }));
13471
+ } finally {
13472
+ setLoading((prev) => ({ ...prev, invoices: false }));
13473
+ }
13474
+ }, "fetchInvoices");
13475
+ const [subscriptions] = await Promise.all([fetchSubscriptions(), fetchPaymentMethods(), fetchInvoices()]);
13476
+ const hasMetered = subscriptions.some(
13477
+ (sub) => sub.price?.recurring?.usageType === "metered"
13478
+ );
13479
+ if (hasMetered) {
13480
+ await fetchUsageData();
13481
+ } else {
13482
+ setLoading((prev) => ({ ...prev, usage: false }));
13483
+ }
13484
+ }
13485
+ }, []);
13486
+ const handleCreateCustomer = /* @__PURE__ */ __name(async () => {
13487
+ setCreatingCustomer(true);
13488
+ try {
13489
+ await StripeCustomerService.createCustomer();
13490
+ setNoCustomerExists(false);
13491
+ await fetchAllData();
13492
+ } catch (error) {
13493
+ console.error("[BillingDashboard] Failed to create customer:", error);
13494
+ setErrors((prev) => ({ ...prev, customer: "Failed to set up billing" }));
13495
+ } finally {
13496
+ setCreatingCustomer(false);
13497
+ }
13498
+ }, "handleCreateCustomer");
13499
+ const fetchUsageData = /* @__PURE__ */ __name(async () => {
13500
+ try {
13501
+ const meters = await StripeUsageService.listMeters();
13502
+ setData((prev) => ({ ...prev, meters }));
13503
+ const summariesMap = {};
13504
+ const now = /* @__PURE__ */ new Date();
13505
+ const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
13506
+ const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
13507
+ for (const meter of meters) {
13508
+ try {
13509
+ const meterSummaries = await StripeUsageService.getMeterSummaries({
13510
+ meterId: meter.id,
13511
+ startTime: startOfMonth,
13512
+ endTime: endOfMonth
13513
+ });
13514
+ summariesMap[meter.id] = meterSummaries.length > 0 ? meterSummaries[0] : null;
13515
+ } catch (error) {
13516
+ console.error(`[BillingDashboard] Failed to load summaries for meter ${meter.id}:`, error);
13517
+ summariesMap[meter.id] = null;
13518
+ }
13519
+ }
13520
+ setData((prev) => ({ ...prev, meterSummaries: summariesMap }));
13521
+ setErrors((prev) => ({ ...prev, usage: null }));
13522
+ } catch (error) {
13523
+ console.error("[BillingDashboard] Failed to load usage data:", error);
13524
+ setErrors((prev) => ({ ...prev, usage: "Failed to load usage data" }));
13525
+ } finally {
13526
+ setLoading((prev) => ({ ...prev, usage: false }));
13527
+ }
13528
+ }, "fetchUsageData");
13529
+ const refreshData = useCallback18(async () => {
13530
+ setLoading({
13531
+ customer: true,
13532
+ subscriptions: true,
13533
+ paymentMethods: true,
13534
+ invoices: true,
13535
+ usage: true
13536
+ });
13537
+ await fetchAllData();
13538
+ }, [fetchAllData]);
13539
+ useEffect47(() => {
13540
+ fetchAllData();
13541
+ }, [fetchAllData]);
13542
+ const criticalSubscriptions = data.subscriptions.filter(
13543
+ (sub) => sub.status === "past_due" /* PAST_DUE */ || sub.status === "trialing" /* TRIALING */ && sub.trialEnd && new Date(sub.trialEnd).getTime() - (/* @__PURE__ */ new Date()).getTime() <= 7 * 24 * 60 * 60 * 1e3
13544
+ );
13545
+ const handleModalClose = /* @__PURE__ */ __name((open) => {
13546
+ if (!open) {
13547
+ setActiveModal(null);
13548
+ refreshData();
13549
+ }
13550
+ }, "handleModalClose");
13551
+ const getModalTitle = /* @__PURE__ */ __name((type) => {
13552
+ switch (type) {
13553
+ case "subscriptions":
13554
+ return "Manage Subscriptions";
13555
+ case "payment-methods":
13556
+ return "Payment Methods";
13557
+ case "invoices":
13558
+ return "Invoice History";
13559
+ case "usage":
13560
+ return "Usage Tracking";
13561
+ default:
13562
+ return "";
13563
+ }
13564
+ }, "getModalTitle");
13565
+ const isInitialLoading = loading.customer && !noCustomerExists && !data.customer;
13566
+ return /* @__PURE__ */ jsxs110("div", { className: "flex w-full flex-col gap-y-6", children: [
13567
+ /* @__PURE__ */ jsxs110("div", { className: "flex items-center gap-x-3", children: [
13568
+ /* @__PURE__ */ jsx172(Wallet2, { className: "h-8 w-8" }),
13569
+ /* @__PURE__ */ jsx172("h1", { className: "text-3xl font-bold", children: "Billing" })
13570
+ ] }),
13571
+ isInitialLoading && /* @__PURE__ */ jsx172(Card, { children: /* @__PURE__ */ jsx172(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx172(Loader24, { className: "h-8 w-8 animate-spin text-muted-foreground" }) }) }),
13572
+ noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs110(Card, { children: [
13573
+ /* @__PURE__ */ jsxs110(CardHeader, { className: "text-center", children: [
13574
+ /* @__PURE__ */ jsx172("div", { className: "mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10", children: /* @__PURE__ */ jsx172(CreditCard4, { className: "h-8 w-8 text-primary" }) }),
13575
+ /* @__PURE__ */ jsx172(CardTitle, { children: "Set Up Billing" }),
13576
+ /* @__PURE__ */ jsx172(CardDescription, { children: "Your company doesn't have a billing account yet. Set one up to manage subscriptions, payment methods, and view invoices." })
13577
+ ] }),
13578
+ /* @__PURE__ */ jsx172(CardContent, { className: "flex justify-center pb-8", children: /* @__PURE__ */ jsx172(Button, { onClick: handleCreateCustomer, disabled: creatingCustomer, size: "lg", children: creatingCustomer ? /* @__PURE__ */ jsxs110(Fragment33, { children: [
13579
+ /* @__PURE__ */ jsx172(Loader24, { className: "mr-2 h-4 w-4 animate-spin" }),
13580
+ "Setting up..."
13581
+ ] }) : "Set Up Billing Account" }) }),
13582
+ errors.customer && /* @__PURE__ */ jsx172(CardContent, { className: "pt-0", children: /* @__PURE__ */ jsx172("p", { className: "text-center text-sm text-destructive", children: errors.customer }) })
13583
+ ] }),
13584
+ !noCustomerExists && !isInitialLoading && /* @__PURE__ */ jsxs110(Fragment33, { children: [
13585
+ criticalSubscriptions.map((subscription) => /* @__PURE__ */ jsx172(
13586
+ BillingAlertBanner,
13587
+ {
13588
+ subscription,
13589
+ onUpdatePayment: () => setActiveModal("payment-methods"),
13590
+ onAddPayment: () => setActiveModal("payment-methods")
13591
+ },
13592
+ subscription.id
13593
+ )),
13594
+ /* @__PURE__ */ jsxs110("div", { className: "grid gap-4 md:grid-cols-2", children: [
13595
+ /* @__PURE__ */ jsx172(
13596
+ SubscriptionSummaryCard,
13597
+ {
13598
+ subscriptions: data.subscriptions,
13599
+ loading: loading.subscriptions,
13600
+ error: errors.subscriptions || void 0,
13601
+ onManageClick: () => setActiveModal("subscriptions")
13602
+ }
13603
+ ),
13604
+ /* @__PURE__ */ jsx172(
13605
+ PaymentMethodSummaryCard,
13606
+ {
13607
+ paymentMethods: data.paymentMethods,
13608
+ defaultPaymentMethodId: data.customer?.defaultPaymentMethodId,
13609
+ loading: loading.paymentMethods,
13610
+ error: errors.paymentMethods || void 0,
13611
+ onManageClick: () => setActiveModal("payment-methods")
13612
+ }
13613
+ ),
13614
+ /* @__PURE__ */ jsx172(
13615
+ CustomerInfoCard,
13616
+ {
13617
+ customer: data.customer,
13618
+ loading: loading.customer,
13619
+ error: errors.customer || void 0
13620
+ }
13621
+ ),
13622
+ /* @__PURE__ */ jsx172(
13623
+ InvoicesSummaryCard,
13624
+ {
13625
+ invoices: data.invoices,
13626
+ loading: loading.invoices,
13627
+ error: errors.invoices || void 0,
13628
+ onViewAllClick: () => setActiveModal("invoices")
13629
+ }
13630
+ ),
13631
+ hasMeteredSubscriptions() && /* @__PURE__ */ jsx172(
13632
+ BillingUsageSummaryCard,
13633
+ {
13634
+ meters: data.meters,
13635
+ summaries: data.meterSummaries,
13636
+ loading: loading.usage,
13637
+ error: errors.usage || void 0,
13638
+ onViewDetailsClick: () => setActiveModal("usage")
13639
+ }
13640
+ )
13641
+ ] }),
13642
+ /* @__PURE__ */ jsx172(
13643
+ BillingDetailModal,
13644
+ {
13645
+ open: activeModal === "subscriptions",
13646
+ onOpenChange: handleModalClose,
13647
+ title: getModalTitle("subscriptions"),
13648
+ children: /* @__PURE__ */ jsx172(SubscriptionsContainer, {})
13649
+ }
13650
+ ),
13651
+ /* @__PURE__ */ jsx172(
13652
+ BillingDetailModal,
13653
+ {
13654
+ open: activeModal === "payment-methods",
13655
+ onOpenChange: handleModalClose,
13656
+ title: getModalTitle("payment-methods"),
13657
+ children: /* @__PURE__ */ jsx172(PaymentMethodsContainer, {})
13658
+ }
13659
+ ),
13660
+ /* @__PURE__ */ jsx172(
13661
+ BillingDetailModal,
13662
+ {
13663
+ open: activeModal === "invoices",
13664
+ onOpenChange: handleModalClose,
13665
+ title: getModalTitle("invoices"),
13666
+ children: /* @__PURE__ */ jsx172(InvoicesContainer, {})
13667
+ }
13668
+ ),
13669
+ /* @__PURE__ */ jsx172(
13670
+ BillingDetailModal,
13671
+ {
13672
+ open: activeModal === "usage",
13673
+ onOpenChange: handleModalClose,
13674
+ title: getModalTitle("usage"),
13675
+ children: /* @__PURE__ */ jsx172(UsageContainer, {})
13676
+ }
13677
+ )
13678
+ ] })
13679
+ ] });
13680
+ }
13681
+ __name(BillingDashboardContainer, "BillingDashboardContainer");
13682
+
13683
+ // src/features/billing/components/providers/StripeProvider.tsx
13684
+ import { Elements } from "@stripe/react-stripe-js";
13685
+ import { loadStripe } from "@stripe/stripe-js";
13686
+ import { useMemo as useMemo18 } from "react";
13687
+ import { Fragment as Fragment34, jsx as jsx173 } from "react/jsx-runtime";
13688
+ var stripePromiseCache = null;
13689
+ function getStripePromise(publishableKey) {
13690
+ if (!publishableKey) {
13691
+ return Promise.resolve(null);
13692
+ }
13693
+ if (stripePromiseCache?.key === publishableKey) {
13694
+ return stripePromiseCache.promise;
13695
+ }
13696
+ const promise = loadStripe(publishableKey);
13697
+ stripePromiseCache = { key: publishableKey, promise };
13698
+ return promise;
13699
+ }
13700
+ __name(getStripePromise, "getStripePromise");
13701
+ function StripeProvider({ children }) {
13702
+ const publishableKey = getStripePublishableKey();
13703
+ const stripePromise = useMemo18(() => getStripePromise(publishableKey), [publishableKey]);
13704
+ const options = useMemo18(() => ({}), []);
13705
+ if (!publishableKey) {
13706
+ return /* @__PURE__ */ jsx173(Fragment34, { children });
13707
+ }
13708
+ return /* @__PURE__ */ jsx173(Elements, { stripe: stripePromise, options, children });
13709
+ }
13710
+ __name(StripeProvider, "StripeProvider");
13711
+ function isStripeConfigured() {
13712
+ return !!getStripePublishableKey();
13713
+ }
13714
+ __name(isStripeConfigured, "isStripeConfigured");
13715
+
13716
+ // src/features/billing/stripe-price/components/forms/PriceEditor.tsx
13717
+ import { zodResolver as zodResolver11 } from "@hookform/resolvers/zod";
13718
+ import { AlertCircle as AlertCircle2, PlusIcon, XIcon as XIcon5 } from "lucide-react";
13719
+ import { useState as useState63 } from "react";
13720
+ import { useForm as useForm11 } from "react-hook-form";
13721
+ import { v4 as v47 } from "uuid";
13722
+ import { z as z11 } from "zod";
13723
+ import { jsx as jsx174, jsxs as jsxs111 } from "react/jsx-runtime";
13724
+ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
13725
+ const [isSubmitting, setIsSubmitting] = useState63(false);
13726
+ const formSchema2 = z11.object({
13727
+ unitAmount: z11.preprocess(
13728
+ (val) => typeof val === "string" ? parseFloat(val) : val,
13729
+ z11.number().min(0, { message: "Amount must be 0 or greater" })
13730
+ ),
13731
+ currency: z11.string().min(1, { message: "Currency is required" }),
13732
+ interval: z11.enum(["one_time", "day", "week", "month", "year"]),
13733
+ intervalCount: z11.preprocess(
13734
+ (val) => val === "" || val === void 0 ? void 0 : typeof val === "string" ? parseInt(val, 10) : val,
13735
+ z11.number().min(1).optional()
13736
+ ),
13737
+ usageType: z11.enum(["licensed", "metered"]).optional(),
13738
+ nickname: z11.string().optional(),
13739
+ active: z11.boolean(),
13740
+ description: z11.string().optional(),
13741
+ features: z11.array(z11.string())
13742
+ });
13743
+ const isEditMode = !!price;
13744
+ const defaultUnitAmount = price?.unitAmount ? price.unitAmount / 100 : 0;
13745
+ const form = useForm11({
13746
+ resolver: zodResolver11(formSchema2),
13747
+ defaultValues: {
13748
+ unitAmount: defaultUnitAmount,
13749
+ currency: price?.currency || "usd",
13750
+ interval: price?.priceType === "one_time" ? "one_time" : price?.recurring?.interval || "month",
13751
+ intervalCount: price?.recurring?.intervalCount || 1,
13752
+ usageType: price?.recurring?.usageType || "licensed",
13753
+ nickname: price?.nickname || "",
13754
+ active: price?.active ?? true,
13755
+ description: price?.description || "",
13756
+ features: price?.features || []
13757
+ }
13758
+ });
13759
+ const watchInterval = form.watch("interval");
13760
+ const isRecurring = watchInterval !== "one_time";
13761
+ const onSubmit = /* @__PURE__ */ __name(async (values) => {
13762
+ setIsSubmitting(true);
13763
+ try {
13764
+ const unitAmountInCents = Math.round(values.unitAmount * 100);
13765
+ if (isEditMode) {
13766
+ await StripePriceService.updatePrice({
13767
+ id: price.id,
13768
+ nickname: values.nickname || void 0,
13769
+ description: values.description || void 0,
13770
+ features: values.features.filter((f) => f.trim()) || void 0
13771
+ });
13772
+ } else {
13773
+ const createInput = {
13774
+ id: v47(),
13775
+ productId,
13776
+ currency: values.currency,
13777
+ unitAmount: unitAmountInCents
13778
+ };
13779
+ if (isRecurring) {
13780
+ createInput.recurring = {
13781
+ interval: values.interval,
13782
+ intervalCount: values.intervalCount || 1,
13783
+ usageType: values.usageType || "licensed"
13784
+ };
13785
+ }
13786
+ if (values.nickname) {
13787
+ createInput.nickname = values.nickname;
13788
+ }
13789
+ if (values.description) {
13790
+ createInput.description = values.description;
13791
+ }
13792
+ const filteredFeatures = values.features.filter((f) => f.trim());
13793
+ if (filteredFeatures.length > 0) {
13794
+ createInput.features = filteredFeatures;
13795
+ }
13796
+ await StripePriceService.createPrice(createInput);
13797
+ }
13798
+ onSuccess();
13799
+ onOpenChange(false);
13800
+ } catch (error) {
13801
+ console.error("[PriceEditor] Failed to save price:", error);
13802
+ } finally {
13803
+ setIsSubmitting(false);
13804
+ }
13805
+ }, "onSubmit");
13806
+ const currencyOptions = [
13807
+ { id: "usd", text: "USD ($)" },
13808
+ { id: "eur", text: "EUR (\u20AC)" },
13809
+ { id: "gbp", text: "GBP (\xA3)" }
13810
+ ];
13811
+ const intervalOptions = [
13812
+ { id: "one_time", text: "One-time" },
13813
+ { id: "day", text: "Daily" },
13814
+ { id: "week", text: "Weekly" },
13815
+ { id: "month", text: "Monthly" },
13816
+ { id: "year", text: "Yearly" }
13817
+ ];
13818
+ const usageTypeOptions = [
13819
+ { id: "licensed", text: "Licensed (per unit)" },
13820
+ { id: "metered", text: "Metered (usage-based)" }
13821
+ ];
13822
+ return /* @__PURE__ */ jsx174(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs111(DialogContent, { className: "max-w-2xl", children: [
13823
+ /* @__PURE__ */ jsxs111(DialogHeader, { children: [
13824
+ /* @__PURE__ */ jsx174(DialogTitle, { children: isEditMode ? "Edit Price" : "Create Price" }),
13825
+ /* @__PURE__ */ jsx174(DialogDescription, { children: isEditMode ? "Update the price details. Note: Only nickname and active status can be changed." : "Create a new price for this product" })
13826
+ ] }),
13827
+ isEditMode && /* @__PURE__ */ jsxs111("div", { className: "bg-blue-50 border border-blue-200 rounded-lg p-4 flex gap-x-3", children: [
13828
+ /* @__PURE__ */ jsx174(AlertCircle2, { className: "h-5 w-5 text-blue-600 flex-shrink-0 mt-0.5" }),
13829
+ /* @__PURE__ */ jsxs111("div", { className: "text-sm text-blue-800", children: [
13830
+ /* @__PURE__ */ jsx174("p", { className: "font-semibold mb-1", children: "Stripe Price Immutability" }),
13831
+ /* @__PURE__ */ jsx174("p", { children: "Due to Stripe's architecture, only the nickname and active status can be modified after creation. To change amount, currency, or billing interval, create a new price." })
13832
+ ] })
13833
+ ] }),
13834
+ /* @__PURE__ */ jsx174(Form, { ...form, children: /* @__PURE__ */ jsxs111("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
13835
+ /* @__PURE__ */ jsxs111("div", { className: "grid grid-cols-2 gap-x-4", children: [
13836
+ /* @__PURE__ */ jsx174(
13837
+ FormInput,
13838
+ {
13839
+ form,
13840
+ id: "unitAmount",
13841
+ name: "Amount (in dollars)",
13842
+ placeholder: "9.99",
13843
+ disabled: isEditMode,
13844
+ isRequired: true
13845
+ }
13846
+ ),
13847
+ /* @__PURE__ */ jsx174(FormSelect, { form, id: "currency", name: "Currency", values: currencyOptions, disabled: isEditMode })
13848
+ ] }),
13849
+ /* @__PURE__ */ jsx174(
13850
+ FormSelect,
13851
+ {
13852
+ form,
13853
+ id: "interval",
13854
+ name: "Billing Interval",
13855
+ values: intervalOptions,
13856
+ disabled: isEditMode
13857
+ }
13858
+ ),
13859
+ isRecurring && /* @__PURE__ */ jsxs111("div", { className: "grid grid-cols-2 gap-x-4", children: [
13860
+ /* @__PURE__ */ jsx174(
13861
+ FormInput,
13862
+ {
13863
+ form,
13864
+ id: "intervalCount",
13865
+ name: "Interval Count",
13866
+ placeholder: "1",
13867
+ type: "number",
13868
+ disabled: isEditMode
13869
+ }
13870
+ ),
13871
+ /* @__PURE__ */ jsx174(
13872
+ FormSelect,
13873
+ {
13874
+ form,
13875
+ id: "usageType",
13876
+ name: "Usage Type",
13877
+ values: usageTypeOptions,
13878
+ disabled: isEditMode
13879
+ }
13880
+ )
13881
+ ] }),
13882
+ /* @__PURE__ */ jsx174(
13883
+ FormInput,
13884
+ {
13885
+ form,
13886
+ id: "nickname",
13887
+ name: "Nickname (optional)",
13888
+ placeholder: "e.g., Standard Plan, Pro Tier"
13889
+ }
13890
+ ),
13891
+ /* @__PURE__ */ jsx174(
13892
+ FormTextarea,
13893
+ {
13894
+ form,
13895
+ id: "description",
13896
+ name: "Description (optional)",
13897
+ placeholder: "Describe what this price tier includes...",
13898
+ className: "min-h-24"
13899
+ }
13900
+ ),
13901
+ /* @__PURE__ */ jsxs111(FormItem, { children: [
13902
+ /* @__PURE__ */ jsx174(FormLabel, { children: "Features (optional)" }),
13903
+ /* @__PURE__ */ jsxs111("div", { className: "space-y-2", children: [
13904
+ form.watch("features").map((_, index) => /* @__PURE__ */ jsxs111("div", { className: "flex gap-2", children: [
13905
+ /* @__PURE__ */ jsx174(FormControl, { children: /* @__PURE__ */ jsx174(
13906
+ Input,
13907
+ {
13908
+ ...form.register(`features.${index}`),
13909
+ placeholder: `Feature ${index + 1}`,
13910
+ className: "flex-1"
13911
+ }
13912
+ ) }),
13913
+ /* @__PURE__ */ jsx174(
13914
+ Button,
13915
+ {
13916
+ type: "button",
13917
+ variant: "outline",
13918
+ size: "icon",
13919
+ onClick: () => {
13920
+ const currentFeatures = form.getValues("features");
13921
+ form.setValue(
13922
+ "features",
13923
+ currentFeatures.filter((_2, i) => i !== index)
13924
+ );
13925
+ },
13926
+ children: /* @__PURE__ */ jsx174(XIcon5, { className: "h-4 w-4" })
13927
+ }
13928
+ )
13929
+ ] }, index)),
13930
+ /* @__PURE__ */ jsxs111(
13931
+ Button,
13932
+ {
13933
+ type: "button",
13934
+ variant: "outline",
13935
+ size: "sm",
13936
+ onClick: () => {
13937
+ const currentFeatures = form.getValues("features");
13938
+ form.setValue("features", [...currentFeatures, ""]);
13939
+ },
13940
+ className: "mt-2",
13941
+ children: [
13942
+ /* @__PURE__ */ jsx174(PlusIcon, { className: "h-4 w-4 mr-2" }),
13943
+ "Add Feature"
13944
+ ]
13945
+ }
13946
+ )
13947
+ ] })
13948
+ ] }),
13949
+ /* @__PURE__ */ jsx174(FormCheckbox, { form, id: "active", name: "Active" }),
13950
+ /* @__PURE__ */ jsx174(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
13951
+ ] }) })
13952
+ ] }) });
13953
+ }
13954
+ __name(PriceEditor, "PriceEditor");
13955
+
13956
+ // src/features/billing/stripe-price/components/lists/PricesList.tsx
13957
+ import { Archive, DollarSign, Edit, RotateCcw } from "lucide-react";
13958
+ import { useEffect as useEffect48, useState as useState64 } from "react";
13959
+ import { jsx as jsx175, jsxs as jsxs112 } from "react/jsx-runtime";
13960
+ function PricesList({ productId, onPricesChange }) {
13961
+ const [prices, setPrices] = useState64([]);
13962
+ const [loading, setLoading] = useState64(true);
13963
+ const [showCreatePrice, setShowCreatePrice] = useState64(false);
13964
+ const [editingPrice, setEditingPrice] = useState64(null);
13965
+ const [priceToArchive, setPriceToArchive] = useState64(null);
13966
+ const [priceToReactivate, setPriceToReactivate] = useState64(null);
13967
+ const [archivingPriceId, setArchivingPriceId] = useState64(null);
13968
+ const [reactivatingPriceId, setReactivatingPriceId] = useState64(null);
13969
+ const loadPrices = /* @__PURE__ */ __name(async () => {
13970
+ setLoading(true);
13971
+ try {
13972
+ const fetchedPrices = await StripePriceService.listPrices({ productId });
13973
+ setPrices(fetchedPrices);
13974
+ } catch (error) {
13975
+ console.error("[PricesList] Failed to load prices:", error);
13976
+ } finally {
13977
+ setLoading(false);
13978
+ }
13979
+ }, "loadPrices");
13980
+ useEffect48(() => {
13981
+ loadPrices();
13982
+ }, [productId]);
13983
+ const handleArchive = /* @__PURE__ */ __name(async () => {
13984
+ if (!priceToArchive) {
13985
+ return;
13986
+ }
13987
+ setArchivingPriceId(priceToArchive.id);
13988
+ try {
13989
+ await StripePriceService.archivePrice({ id: priceToArchive.id });
13990
+ setPriceToArchive(null);
13991
+ await loadPrices();
13992
+ onPricesChange();
13993
+ } catch (error) {
13994
+ console.error("[PricesList] Failed to archive price:", error);
13995
+ } finally {
13996
+ setArchivingPriceId(null);
13997
+ }
13998
+ }, "handleArchive");
13999
+ const handleReactivate = /* @__PURE__ */ __name(async () => {
14000
+ if (!priceToReactivate) {
14001
+ return;
14002
+ }
14003
+ setReactivatingPriceId(priceToReactivate.id);
14004
+ try {
14005
+ await StripePriceService.reactivatePrice({ id: priceToReactivate.id });
14006
+ setPriceToReactivate(null);
14007
+ await loadPrices();
14008
+ onPricesChange();
14009
+ } catch (error) {
14010
+ console.error("[PricesList] Failed to reactivate price:", error);
14011
+ } finally {
14012
+ setReactivatingPriceId(null);
14013
+ }
14014
+ }, "handleReactivate");
14015
+ const formatInterval2 = /* @__PURE__ */ __name((price) => {
14016
+ if (price.priceType === "one_time") {
14017
+ return "one-time";
14018
+ }
14019
+ if (price.recurring) {
14020
+ const count = price.recurring.intervalCount;
14021
+ const interval = price.recurring.interval;
14022
+ if (count === 1) {
14023
+ return `/ ${interval}`;
14024
+ } else {
14025
+ return `/ ${count} ${interval}s`;
14026
+ }
14027
+ }
14028
+ return "";
14029
+ }, "formatInterval");
14030
+ if (loading) {
14031
+ return /* @__PURE__ */ jsx175("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx175("p", { className: "text-muted-foreground", children: "Loading prices..." }) });
14032
+ }
14033
+ return /* @__PURE__ */ jsxs112("div", { className: "flex flex-col gap-y-4", children: [
14034
+ /* @__PURE__ */ jsxs112("div", { className: "flex items-center justify-between mb-4", children: [
14035
+ /* @__PURE__ */ jsx175("h4", { className: "text-lg font-semibold", children: "Prices" }),
14036
+ /* @__PURE__ */ jsx175(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
14037
+ ] }),
14038
+ prices.length === 0 && /* @__PURE__ */ jsxs112("div", { className: "bg-background flex flex-col items-center justify-center gap-y-3 rounded-lg border border-dashed p-8", children: [
14039
+ /* @__PURE__ */ jsx175(DollarSign, { className: "text-muted-foreground h-12 w-12" }),
14040
+ /* @__PURE__ */ jsx175("p", { className: "text-muted-foreground text-sm", children: "No prices yet. Add a price to enable subscriptions." }),
14041
+ /* @__PURE__ */ jsx175(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
14042
+ ] }),
14043
+ prices.length > 0 && /* @__PURE__ */ jsx175("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: prices.map((price) => {
14044
+ const isArchiving = archivingPriceId === price.id;
14045
+ const isReactivating = reactivatingPriceId === price.id;
14046
+ return /* @__PURE__ */ jsxs112("div", { className: "border rounded-lg bg-white p-4 hover:shadow-sm transition-shadow", children: [
14047
+ /* @__PURE__ */ jsxs112("div", { className: "flex items-start justify-between mb-3", children: [
14048
+ /* @__PURE__ */ jsx175(DollarSign, { className: "h-5 w-5 text-primary" }),
14049
+ /* @__PURE__ */ jsxs112("div", { className: "flex gap-1", children: [
14050
+ /* @__PURE__ */ jsx175(Button, { variant: "ghost", size: "sm", onClick: () => setEditingPrice(price), className: "h-8 w-8 p-0", children: /* @__PURE__ */ jsx175(Edit, { className: "h-4 w-4" }) }),
14051
+ price.active ? /* @__PURE__ */ jsx175(
14052
+ Button,
14053
+ {
14054
+ variant: "ghost",
14055
+ size: "sm",
14056
+ onClick: () => setPriceToArchive(price),
14057
+ className: "h-8 w-8 p-0",
14058
+ disabled: isArchiving,
14059
+ children: /* @__PURE__ */ jsx175(Archive, { className: "h-4 w-4" })
14060
+ }
14061
+ ) : /* @__PURE__ */ jsx175(
14062
+ Button,
14063
+ {
14064
+ variant: "ghost",
14065
+ size: "sm",
14066
+ onClick: () => setPriceToReactivate(price),
14067
+ className: "h-8 w-8 p-0",
14068
+ disabled: isReactivating,
14069
+ children: /* @__PURE__ */ jsx175(RotateCcw, { className: "h-4 w-4" })
14070
+ }
14071
+ )
14072
+ ] })
14073
+ ] }),
14074
+ /* @__PURE__ */ jsx175("div", { className: "mb-2", children: /* @__PURE__ */ jsxs112("div", { className: "text-2xl font-bold", children: [
14075
+ formatCurrency(price.unitAmount, price.currency),
14076
+ " ",
14077
+ /* @__PURE__ */ jsx175("span", { className: "text-muted-foreground text-sm font-normal", children: formatInterval2(price) })
14078
+ ] }) }),
14079
+ price.metadata?.nickname && /* @__PURE__ */ jsx175("p", { className: "text-sm font-medium mb-2", children: price.metadata.nickname }),
14080
+ /* @__PURE__ */ jsxs112("div", { className: "flex flex-wrap gap-2", children: [
14081
+ price.active ? /* @__PURE__ */ jsx175("span", { className: "bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full font-medium", children: "Active" }) : /* @__PURE__ */ jsx175("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium", children: "Inactive" }),
14082
+ price.recurring?.usageType === "metered" && /* @__PURE__ */ jsx175("span", { className: "bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full font-medium", children: "Metered" }),
14083
+ /* @__PURE__ */ jsx175("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium uppercase", children: price.currency })
14084
+ ] })
14085
+ ] }, price.id);
14086
+ }) }),
14087
+ showCreatePrice && /* @__PURE__ */ jsx175(
14088
+ PriceEditor,
14089
+ {
14090
+ productId,
14091
+ open: showCreatePrice,
14092
+ onOpenChange: setShowCreatePrice,
14093
+ onSuccess: () => {
14094
+ loadPrices();
14095
+ onPricesChange();
14096
+ }
14097
+ }
14098
+ ),
14099
+ editingPrice && /* @__PURE__ */ jsx175(
14100
+ PriceEditor,
14101
+ {
14102
+ productId,
14103
+ price: editingPrice,
14104
+ open: !!editingPrice,
14105
+ onOpenChange: (open) => !open && setEditingPrice(null),
14106
+ onSuccess: () => {
14107
+ loadPrices();
14108
+ onPricesChange();
14109
+ setEditingPrice(null);
14110
+ }
14111
+ }
14112
+ ),
14113
+ /* @__PURE__ */ jsx175(AlertDialog, { open: !!priceToArchive, onOpenChange: (open) => !open && setPriceToArchive(null), children: /* @__PURE__ */ jsxs112(AlertDialogContent, { children: [
14114
+ /* @__PURE__ */ jsxs112(AlertDialogHeader, { children: [
14115
+ /* @__PURE__ */ jsx175(AlertDialogTitle, { children: "Archive Price" }),
14116
+ /* @__PURE__ */ jsxs112(AlertDialogDescription, { children: [
14117
+ "Are you sure you want to archive the price for",
14118
+ " ",
14119
+ priceToArchive && `${formatCurrency(priceToArchive.unitAmount, priceToArchive.currency)} ${formatInterval2(priceToArchive)}`,
14120
+ "? This will prevent new subscriptions but existing ones will continue."
14121
+ ] })
14122
+ ] }),
14123
+ /* @__PURE__ */ jsxs112(AlertDialogFooter, { children: [
14124
+ /* @__PURE__ */ jsx175(AlertDialogCancel, { disabled: !!archivingPriceId, children: "Cancel" }),
14125
+ /* @__PURE__ */ jsx175(
14126
+ AlertDialogAction,
14127
+ {
14128
+ onClick: handleArchive,
14129
+ disabled: !!archivingPriceId,
14130
+ className: "bg-red-600 hover:bg-red-700",
14131
+ children: archivingPriceId ? "Archiving..." : "Archive"
14132
+ }
14133
+ )
14134
+ ] })
14135
+ ] }) }),
14136
+ /* @__PURE__ */ jsx175(AlertDialog, { open: !!priceToReactivate, onOpenChange: (open) => !open && setPriceToReactivate(null), children: /* @__PURE__ */ jsxs112(AlertDialogContent, { children: [
14137
+ /* @__PURE__ */ jsxs112(AlertDialogHeader, { children: [
14138
+ /* @__PURE__ */ jsx175(AlertDialogTitle, { children: "Reactivate Price" }),
14139
+ /* @__PURE__ */ jsxs112(AlertDialogDescription, { children: [
14140
+ "Are you sure you want to reactivate the price for",
14141
+ " ",
14142
+ priceToReactivate && `${formatCurrency(priceToReactivate.unitAmount, priceToReactivate.currency)} ${formatInterval2(priceToReactivate)}`,
14143
+ "? This will allow new subscriptions again."
14144
+ ] })
14145
+ ] }),
14146
+ /* @__PURE__ */ jsxs112(AlertDialogFooter, { children: [
14147
+ /* @__PURE__ */ jsx175(AlertDialogCancel, { disabled: !!reactivatingPriceId, children: "Cancel" }),
14148
+ /* @__PURE__ */ jsx175(
14149
+ AlertDialogAction,
14150
+ {
14151
+ onClick: handleReactivate,
14152
+ disabled: !!reactivatingPriceId,
14153
+ className: "bg-green-600 hover:bg-green-700",
14154
+ children: reactivatingPriceId ? "Reactivating..." : "Reactivate"
14155
+ }
14156
+ )
14157
+ ] })
14158
+ ] }) })
14159
+ ] });
14160
+ }
14161
+ __name(PricesList, "PricesList");
14162
+
14163
+ // src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
14164
+ import { Package as Package2 } from "lucide-react";
14165
+ import { useEffect as useEffect49, useState as useState67 } from "react";
14166
+
14167
+ // src/features/billing/stripe-product/components/forms/ProductEditor.tsx
14168
+ import { zodResolver as zodResolver12 } from "@hookform/resolvers/zod";
14169
+ import { useState as useState65 } from "react";
14170
+ import { useForm as useForm12 } from "react-hook-form";
14171
+ import { v4 as v48 } from "uuid";
14172
+ import { z as z12 } from "zod";
14173
+ import { jsx as jsx176, jsxs as jsxs113 } from "react/jsx-runtime";
14174
+ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
14175
+ const [isSubmitting, setIsSubmitting] = useState65(false);
14176
+ const formSchema2 = z12.object({
14177
+ name: z12.string().min(1, { message: "Product name is required" }),
14178
+ description: z12.string().optional(),
14179
+ active: z12.boolean()
14180
+ });
14181
+ const form = useForm12({
14182
+ resolver: zodResolver12(formSchema2),
14183
+ defaultValues: {
14184
+ name: product?.name || "",
14185
+ description: product?.description || "",
14186
+ active: product?.active ?? true
14187
+ }
14188
+ });
14189
+ const onSubmit = /* @__PURE__ */ __name(async (values) => {
14190
+ setIsSubmitting(true);
14191
+ try {
14192
+ if (product) {
14193
+ await StripeProductService.updateProduct({
14194
+ id: product.id,
14195
+ name: values.name,
14196
+ description: values.description,
14197
+ active: values.active
14198
+ });
14199
+ } else {
14200
+ await StripeProductService.createProduct({
14201
+ id: v48(),
14202
+ name: values.name,
14203
+ description: values.description,
14204
+ active: values.active
14205
+ });
14206
+ }
14207
+ onSuccess();
14208
+ onOpenChange(false);
14209
+ } catch (error) {
14210
+ console.error("[ProductEditor] Failed to save product:", error);
14211
+ } finally {
14212
+ setIsSubmitting(false);
14213
+ }
14214
+ }, "onSubmit");
14215
+ return /* @__PURE__ */ jsx176(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs113(DialogContent, { className: "max-w-2xl", children: [
14216
+ /* @__PURE__ */ jsxs113(DialogHeader, { children: [
14217
+ /* @__PURE__ */ jsx176(DialogTitle, { children: product ? "Edit Product" : "Create Product" }),
14218
+ /* @__PURE__ */ jsx176(DialogDescription, { children: product ? `Update the details for ${product.name}` : "Create a new product to offer to your customers" })
14219
+ ] }),
14220
+ /* @__PURE__ */ jsx176(Form, { ...form, children: /* @__PURE__ */ jsxs113("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
14221
+ /* @__PURE__ */ jsx176(FormInput, { form, id: "name", name: "Product Name", placeholder: "Enter product name", isRequired: true }),
14222
+ /* @__PURE__ */ jsx176(
14223
+ FormTextarea,
14224
+ {
14225
+ form,
14226
+ id: "description",
14227
+ name: "Description",
14228
+ placeholder: "Enter product description (optional)",
14229
+ className: "min-h-32"
14230
+ }
14231
+ ),
14232
+ /* @__PURE__ */ jsx176(FormCheckbox, { form, id: "active", name: "Active" }),
14233
+ /* @__PURE__ */ jsx176(CommonEditorButtons, { isEdit: !!product, form, disabled: isSubmitting, setOpen: onOpenChange })
14234
+ ] }) })
14235
+ ] }) });
14236
+ }
14237
+ __name(ProductEditor, "ProductEditor");
14238
+
14239
+ // src/features/billing/stripe-product/components/lists/ProductsList.tsx
14240
+ import { Archive as Archive2, ChevronDown as ChevronDown3, ChevronUp as ChevronUp2, Edit as Edit2, Package, RefreshCw as RefreshCw3 } from "lucide-react";
14241
+ import { useState as useState66 } from "react";
14242
+ import { jsx as jsx177, jsxs as jsxs114 } from "react/jsx-runtime";
14243
+ function ProductsList({ products, onProductsChange }) {
14244
+ const [expandedProductId, setExpandedProductId] = useState66(null);
14245
+ const [editingProduct, setEditingProduct] = useState66(null);
14246
+ const [archivingProductId, setArchivingProductId] = useState66(null);
14247
+ const [reactivatingProductId, setReactivatingProductId] = useState66(null);
14248
+ const [productToArchive, setProductToArchive] = useState66(null);
14249
+ const [productToReactivate, setProductToReactivate] = useState66(null);
14250
+ const handleArchive = /* @__PURE__ */ __name(async () => {
14251
+ if (!productToArchive) {
14252
+ return;
14253
+ }
14254
+ setArchivingProductId(productToArchive.id);
14255
+ try {
14256
+ const archivedProduct = await StripeProductService.archiveProduct({ id: productToArchive.id });
14257
+ setProductToArchive(null);
14258
+ onProductsChange();
14259
+ } catch (error) {
14260
+ console.error("[ProductsList] Failed to archive product:", error);
14261
+ } finally {
14262
+ setArchivingProductId(null);
14263
+ }
14264
+ }, "handleArchive");
14265
+ const handleReactivate = /* @__PURE__ */ __name(async () => {
14266
+ if (!productToReactivate) {
14267
+ return;
14268
+ }
14269
+ setReactivatingProductId(productToReactivate.id);
14270
+ try {
14271
+ const reactivatedProduct = await StripeProductService.reactivateProduct({ id: productToReactivate.id });
14272
+ setProductToReactivate(null);
14273
+ onProductsChange();
14274
+ } catch (error) {
14275
+ } finally {
14276
+ setReactivatingProductId(null);
14277
+ }
14278
+ }, "handleReactivate");
14279
+ const toggleExpand = /* @__PURE__ */ __name((productId) => {
14280
+ setExpandedProductId(expandedProductId === productId ? null : productId);
14281
+ }, "toggleExpand");
14282
+ return /* @__PURE__ */ jsxs114("div", { className: "flex flex-col gap-y-4", children: [
14283
+ products.map((product) => {
14284
+ const isExpanded = expandedProductId === product.id;
14285
+ const isArchiving = archivingProductId === product.id;
14286
+ const isReactivating = reactivatingProductId === product.id;
14287
+ return /* @__PURE__ */ jsxs114("div", { className: "border rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow", children: [
14288
+ /* @__PURE__ */ jsxs114("div", { className: "flex items-center justify-between p-6", children: [
14289
+ /* @__PURE__ */ jsxs114("div", { className: "flex items-center gap-x-4 flex-1", children: [
14290
+ /* @__PURE__ */ jsx177(Package, { className: "h-6 w-6 text-primary" }),
14291
+ /* @__PURE__ */ jsxs114("div", { className: "flex-1", children: [
14292
+ /* @__PURE__ */ jsxs114("div", { className: "flex items-center gap-x-3", children: [
14293
+ /* @__PURE__ */ jsx177("h3", { className: "text-lg font-semibold", children: product.name }),
14294
+ product.active ? /* @__PURE__ */ jsx177("span", { className: "bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full font-medium", children: "Active" }) : /* @__PURE__ */ jsx177("span", { className: "bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium", children: "Inactive" })
14295
+ ] }),
14296
+ product.description && /* @__PURE__ */ jsx177("p", { className: "text-muted-foreground text-sm mt-1", children: product.description })
14297
+ ] })
14298
+ ] }),
14299
+ /* @__PURE__ */ jsxs114("div", { className: "flex items-center gap-x-2", children: [
14300
+ /* @__PURE__ */ jsxs114(Button, { variant: "outline", size: "sm", onClick: () => setEditingProduct(product), children: [
14301
+ /* @__PURE__ */ jsx177(Edit2, { className: "h-4 w-4 mr-1" }),
14302
+ "Edit"
14303
+ ] }),
14304
+ product.active ? /* @__PURE__ */ jsxs114(
14305
+ Button,
14306
+ {
14307
+ variant: "outline",
14308
+ size: "sm",
14309
+ onClick: () => setProductToArchive(product),
14310
+ disabled: isArchiving,
14311
+ children: [
14312
+ /* @__PURE__ */ jsx177(Archive2, { className: "h-4 w-4 mr-1" }),
14313
+ isArchiving ? "Archiving..." : "Archive"
14314
+ ]
14315
+ }
14316
+ ) : /* @__PURE__ */ jsxs114(
14317
+ Button,
14318
+ {
14319
+ variant: "outline",
14320
+ size: "sm",
14321
+ onClick: () => setProductToReactivate(product),
14322
+ disabled: isReactivating,
14323
+ children: [
14324
+ /* @__PURE__ */ jsx177(RefreshCw3, { className: "h-4 w-4 mr-1" }),
14325
+ isReactivating ? "Reactivating..." : "Reactivate"
14326
+ ]
14327
+ }
14328
+ ),
14329
+ /* @__PURE__ */ jsx177(Button, { variant: "ghost", size: "sm", onClick: () => toggleExpand(product.id), children: isExpanded ? /* @__PURE__ */ jsx177(ChevronUp2, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx177(ChevronDown3, { className: "h-5 w-5" }) })
14330
+ ] })
14331
+ ] }),
14332
+ isExpanded && /* @__PURE__ */ jsx177("div", { className: "border-t bg-muted/30 p-6", children: /* @__PURE__ */ jsx177(PricesList, { productId: product.id, onPricesChange: onProductsChange }) })
14333
+ ] }, product.id);
14334
+ }),
14335
+ editingProduct && /* @__PURE__ */ jsx177(
14336
+ ProductEditor,
14337
+ {
14338
+ product: editingProduct,
14339
+ open: !!editingProduct,
14340
+ onOpenChange: (open) => !open && setEditingProduct(null),
14341
+ onSuccess: () => {
14342
+ onProductsChange();
14343
+ setEditingProduct(null);
14344
+ }
14345
+ }
14346
+ ),
14347
+ /* @__PURE__ */ jsx177(AlertDialog, { open: !!productToArchive, onOpenChange: (open) => !open && setProductToArchive(null), children: /* @__PURE__ */ jsxs114(AlertDialogContent, { children: [
14348
+ /* @__PURE__ */ jsxs114(AlertDialogHeader, { children: [
14349
+ /* @__PURE__ */ jsx177(AlertDialogTitle, { children: "Archive Product" }),
14350
+ /* @__PURE__ */ jsxs114(AlertDialogDescription, { children: [
14351
+ 'Are you sure you want to archive "',
14352
+ productToArchive?.name,
14353
+ '"? This will deactivate it and it will no longer be available for new subscriptions.'
14354
+ ] })
14355
+ ] }),
14356
+ /* @__PURE__ */ jsxs114(AlertDialogFooter, { children: [
14357
+ /* @__PURE__ */ jsx177(AlertDialogCancel, { disabled: !!archivingProductId, children: "Cancel" }),
14358
+ /* @__PURE__ */ jsx177(
14359
+ AlertDialogAction,
14360
+ {
14361
+ onClick: handleArchive,
14362
+ disabled: !!archivingProductId,
14363
+ className: "bg-red-600 hover:bg-red-700",
14364
+ children: archivingProductId ? "Archiving..." : "Archive"
14365
+ }
14366
+ )
14367
+ ] })
14368
+ ] }) }),
14369
+ /* @__PURE__ */ jsx177(AlertDialog, { open: !!productToReactivate, onOpenChange: (open) => !open && setProductToReactivate(null), children: /* @__PURE__ */ jsxs114(AlertDialogContent, { children: [
14370
+ /* @__PURE__ */ jsxs114(AlertDialogHeader, { children: [
14371
+ /* @__PURE__ */ jsx177(AlertDialogTitle, { children: "Reactivate Product" }),
14372
+ /* @__PURE__ */ jsxs114(AlertDialogDescription, { children: [
14373
+ 'Are you sure you want to reactivate "',
14374
+ productToReactivate?.name,
14375
+ '"? This will make it available for new subscriptions again.'
14376
+ ] })
14377
+ ] }),
14378
+ /* @__PURE__ */ jsxs114(AlertDialogFooter, { children: [
14379
+ /* @__PURE__ */ jsx177(AlertDialogCancel, { disabled: !!reactivatingProductId, children: "Cancel" }),
14380
+ /* @__PURE__ */ jsx177(
14381
+ AlertDialogAction,
14382
+ {
14383
+ onClick: handleReactivate,
14384
+ disabled: !!reactivatingProductId,
14385
+ className: "bg-green-600 hover:bg-green-700",
14386
+ children: reactivatingProductId ? "Reactivating..." : "Reactivate"
14387
+ }
14388
+ )
14389
+ ] })
14390
+ ] }) })
14391
+ ] });
14392
+ }
14393
+ __name(ProductsList, "ProductsList");
14394
+
14395
+ // src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
14396
+ import { jsx as jsx178, jsxs as jsxs115 } from "react/jsx-runtime";
14397
+ function ProductsAdminContainer() {
14398
+ const { hasRole } = useCurrentUserContext();
14399
+ const [products, setProducts] = useState67([]);
14400
+ const [loading, setLoading] = useState67(true);
14401
+ const [showCreateProduct, setShowCreateProduct] = useState67(false);
14402
+ if (!hasRole(getRoleId().Administrator)) {
14403
+ return /* @__PURE__ */ jsx178("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx178("p", { className: "text-red-600 font-semibold", children: "Permission denied. Administrator access required." }) });
14404
+ }
14405
+ const loadProducts = /* @__PURE__ */ __name(async () => {
14406
+ setLoading(true);
14407
+ try {
14408
+ const fetchedProducts = await StripeProductService.listProducts();
14409
+ setProducts(fetchedProducts);
14410
+ } catch (error) {
14411
+ console.error("[ProductsAdminContainer] Failed to load products:", error);
14412
+ } finally {
14413
+ setLoading(false);
14414
+ }
14415
+ }, "loadProducts");
14416
+ useEffect49(() => {
14417
+ loadProducts();
14418
+ }, []);
14419
+ if (loading) {
14420
+ return /* @__PURE__ */ jsx178("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx178("p", { className: "text-muted-foreground", children: "Loading products..." }) });
14421
+ }
14422
+ return /* @__PURE__ */ jsxs115("div", { className: "flex w-full flex-col gap-y-6", children: [
14423
+ /* @__PURE__ */ jsxs115("div", { className: "flex items-center justify-between", children: [
14424
+ /* @__PURE__ */ jsxs115("div", { className: "flex items-center gap-x-3", children: [
14425
+ /* @__PURE__ */ jsx178(Package2, { className: "h-8 w-8" }),
14426
+ /* @__PURE__ */ jsx178("h1", { className: "text-3xl font-bold", children: "Product & Price Management" })
14427
+ ] }),
14428
+ /* @__PURE__ */ jsx178(Button, { onClick: () => setShowCreateProduct(true), children: "Create Product" })
14429
+ ] }),
14430
+ products.length === 0 && /* @__PURE__ */ jsxs115("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed p-12", children: [
14431
+ /* @__PURE__ */ jsx178(Package2, { className: "text-muted-foreground h-16 w-16" }),
14432
+ /* @__PURE__ */ jsxs115("div", { className: "text-center", children: [
14433
+ /* @__PURE__ */ jsx178("h3", { className: "mb-2 text-xl font-semibold", children: "No products yet" }),
14434
+ /* @__PURE__ */ jsx178("p", { className: "text-muted-foreground mb-4", children: "Create your first product to start offering subscriptions to your customers." }),
14435
+ /* @__PURE__ */ jsx178(Button, { onClick: () => setShowCreateProduct(true), children: "Create Your First Product" })
14436
+ ] })
14437
+ ] }),
14438
+ products.length > 0 && /* @__PURE__ */ jsx178(ProductsList, { products, onProductsChange: loadProducts }),
14439
+ showCreateProduct && /* @__PURE__ */ jsx178(ProductEditor, { open: showCreateProduct, onOpenChange: setShowCreateProduct, onSuccess: loadProducts })
14440
+ ] });
14441
+ }
14442
+ __name(ProductsAdminContainer, "ProductsAdminContainer");
14443
+
14444
+ // src/features/content/components/lists/ContentsList.tsx
14445
+ import { useTranslations as useTranslations53 } from "next-intl";
14446
+ import { jsx as jsx179, jsxs as jsxs116 } from "react/jsx-runtime";
14447
+ function ContentsList({ contentList }) {
14448
+ const t = useTranslations53();
14449
+ return /* @__PURE__ */ jsxs116("div", { className: "flex min-h-0 w-full flex-col overflow-y-auto", children: [
14450
+ /* @__PURE__ */ jsx179("h2", { className: "text-xl font-semibold", children: t(`foundations.content.news`) }),
14451
+ /* @__PURE__ */ jsx179("div", { className: "flex flex-col", children: contentList.map((content) => /* @__PURE__ */ jsx179(ContentsListElement, { content }, content.id)) })
14452
+ ] });
14453
+ }
14454
+ __name(ContentsList, "ContentsList");
14455
+ function ContentsListElement({ content }) {
14456
+ const generateUrl = usePageUrlGenerator();
14457
+ const contentModule = content.contentType ? Modules.findByModelName(content.contentType) : void 0;
14458
+ const link = contentModule ? generateUrl({ page: contentModule, id: content.id }) : "#";
14459
+ return /* @__PURE__ */ jsx179("div", { className: "hover:bg-muted flex w-full flex-col gap-y-2 border-b p-2 py-4", children: /* @__PURE__ */ jsxs116("div", { className: "flex w-full justify-between gap-x-2", children: [
14460
+ /* @__PURE__ */ jsxs116(HoverCard, { children: [
14461
+ /* @__PURE__ */ jsx179(HoverCardTrigger, { asChild: true, children: /* @__PURE__ */ jsxs116(Link2, { href: link, className: "flex w-full items-center justify-start gap-2 font-semibold", children: [
14462
+ contentModule && getIconByModule({ module: contentModule, className: "h-4 w-4" }),
14463
+ content.name
14464
+ ] }) }),
14465
+ /* @__PURE__ */ jsxs116(HoverCardContent, { className: "flex max-h-96 w-96 flex-col gap-y-4 overflow-y-auto", children: [
14466
+ /* @__PURE__ */ jsx179(Link2, { href: link, className: "font-semibold", children: content.name }),
14467
+ /* @__PURE__ */ jsx179("div", { className: "text-xs", children: content.abstract })
14468
+ ] })
14469
+ ] }),
14470
+ /* @__PURE__ */ jsx179(ContributorsList, { content })
14471
+ ] }) });
14472
+ }
14473
+ __name(ContentsListElement, "ContentsListElement");
14474
+
14475
+ // src/features/content/components/lists/ContentsListById.tsx
14476
+ import { useTranslations as useTranslations54 } from "next-intl";
14477
+ import { jsx as jsx180 } from "react/jsx-runtime";
14478
+ function ContentsListById({ contentIds }) {
14479
+ const t = useTranslations54();
14480
+ const data = useDataListRetriever({
14481
+ module: Modules.Content,
14482
+ retriever: /* @__PURE__ */ __name((params) => ContentService.findMany(params), "retriever"),
14483
+ retrieverParams: { contentIds }
14484
+ });
14485
+ return /* @__PURE__ */ jsx180(
14486
+ ContentListTable,
14487
+ {
14488
+ data,
14489
+ fields: ["name" /* name */, "authors" /* authors */, "updatedAt" /* updatedAt */],
14490
+ tableGeneratorType: Modules.Content,
14491
+ title: t(`generic.relevant`)
14492
+ }
14493
+ );
14494
+ }
14495
+ __name(ContentsListById, "ContentsListById");
14496
+
14497
+ // src/features/content/components/lists/RelevantContentsList.tsx
14498
+ import { useTranslations as useTranslations55 } from "next-intl";
14499
+ import { jsx as jsx181 } from "react/jsx-runtime";
14500
+ function RelevantContentsList({ id }) {
14501
+ const t = useTranslations55();
14502
+ const data = useDataListRetriever({
14503
+ module: Modules.Content,
14504
+ retriever: /* @__PURE__ */ __name((params) => ContentService.findRelevant(params), "retriever"),
14505
+ retrieverParams: { id }
14506
+ });
14507
+ return /* @__PURE__ */ jsx181(
14508
+ ContentListTable,
14509
+ {
14510
+ data,
14511
+ fields: ["name" /* name */, "authors" /* authors */, "relevance" /* relevance */, "updatedAt" /* updatedAt */],
14512
+ tableGeneratorType: Modules.Content,
14513
+ title: t(`generic.relevant`)
14514
+ }
14515
+ );
14516
+ }
14517
+ __name(RelevantContentsList, "RelevantContentsList");
14518
+
14519
+ // src/features/notification/components/common/NotificationErrorBoundary.tsx
14520
+ import { Component } from "react";
14521
+ import { jsx as jsx182, jsxs as jsxs117 } from "react/jsx-runtime";
14522
+ var NotificationErrorBoundary = class extends Component {
14523
+ static {
14524
+ __name(this, "NotificationErrorBoundary");
14525
+ }
14526
+ constructor(props) {
14527
+ super(props);
14528
+ this.state = { hasError: false };
14529
+ }
14530
+ static getDerivedStateFromError(error) {
14531
+ return { hasError: true, error };
14532
+ }
14533
+ componentDidCatch(error, errorInfo) {
14534
+ console.error("\u{1F6A8} [NotificationErrorBoundary] Caught error:", error, errorInfo);
14535
+ }
14536
+ render() {
14537
+ if (this.state.hasError) {
14538
+ return this.props.fallback || /* @__PURE__ */ jsx182("div", { className: "flex items-center justify-center p-4 text-center", children: /* @__PURE__ */ jsxs117("div", { className: "text-muted-foreground text-sm", children: [
14539
+ /* @__PURE__ */ jsx182("p", { children: "Something went wrong with notifications." }),
14540
+ /* @__PURE__ */ jsx182(
14541
+ "button",
14542
+ {
14543
+ onClick: () => this.setState({ hasError: false }),
14544
+ className: "text-primary mt-2 underline hover:no-underline",
14545
+ children: "Try again"
14546
+ }
14547
+ )
14548
+ ] }) });
14549
+ }
14550
+ return this.props.children;
14551
+ }
14552
+ };
14553
+
14554
+ // src/features/notification/components/containers/NotificationsListContainer.tsx
14555
+ import { useTranslations as useTranslations57 } from "next-intl";
14556
+
14557
+ // src/features/notification/components/lists/NotificationsList.tsx
14558
+ import { ArchiveIcon } from "lucide-react";
14559
+ import { useTranslations as useTranslations56 } from "next-intl";
14560
+ import { Fragment as Fragment35, jsx as jsx183, jsxs as jsxs118 } from "react/jsx-runtime";
14561
+ function NotificationsList({ archived }) {
14562
+ const t = useTranslations56();
14563
+ const generateUrl = usePageUrlGenerator();
14564
+ const data = useDataListRetriever({
14565
+ retriever: /* @__PURE__ */ __name((params) => NotificationService.findMany(params), "retriever"),
14566
+ retrieverParams: { isArchived: archived },
14567
+ module: Modules.Notification
14568
+ });
14569
+ const archiveNotification = /* @__PURE__ */ __name(async (notification) => {
14570
+ await NotificationService.archive({ id: notification.id });
14571
+ data.removeElement(notification);
14572
+ }, "archiveNotification");
14573
+ const LoadingSkeleton = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx183("div", { className: "space-y-4", children: Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsx183(Card, { children: /* @__PURE__ */ jsx183(CardContent, { className: "p-2", children: /* @__PURE__ */ jsxs118("div", { className: "flex w-full flex-row items-center", children: [
14574
+ /* @__PURE__ */ jsx183(Skeleton, { className: "mr-4 h-8 w-8 rounded-full" }),
14575
+ /* @__PURE__ */ jsxs118("div", { className: "flex-1 space-y-2", children: [
14576
+ /* @__PURE__ */ jsx183(Skeleton, { className: "h-4 w-3/4" }),
14577
+ /* @__PURE__ */ jsx183(Skeleton, { className: "h-3 w-1/2" })
14578
+ ] }),
14579
+ /* @__PURE__ */ jsx183(Skeleton, { className: "h-8 w-20" })
14580
+ ] }) }) }, i)) }), "LoadingSkeleton");
14581
+ return /* @__PURE__ */ jsx183("div", { className: "space-y-4", children: data.isLoaded ? data.data?.map((notification) => {
14582
+ const notificationData = generateNotificationData({ notification, generateUrl });
14583
+ return /* @__PURE__ */ jsx183(Card, { children: /* @__PURE__ */ jsx183(CardContent, { className: "p-0", children: /* @__PURE__ */ jsxs118("div", { className: `flex w-full flex-row items-center p-2`, children: [
14584
+ notificationData.actor ? /* @__PURE__ */ jsx183("div", { className: "flex w-12 max-w-12 px-2", children: /* @__PURE__ */ jsx183(Link2, { href: generateUrl({ page: Modules.User, id: notificationData.actor.id }), children: /* @__PURE__ */ jsx183(UserAvatar, { user: notificationData.actor, className: "h-8 w-8" }) }) }) : /* @__PURE__ */ jsx183("div", { className: "flex w-14 max-w-14 px-2" }),
14585
+ /* @__PURE__ */ jsxs118("div", { className: "flex w-full flex-col", children: [
14586
+ /* @__PURE__ */ jsx183("p", { className: "text-sm", children: t.rich(`foundations.notification.${notification.notificationType}.description`, {
14587
+ strong: /* @__PURE__ */ __name((chunks) => /* @__PURE__ */ jsx183("strong", { children: chunks }), "strong"),
14588
+ actor: notificationData.actor?.name ?? "",
14589
+ title: notificationData.title
14590
+ }) }),
14591
+ /* @__PURE__ */ jsx183("div", { className: "text-muted-foreground mt-1 w-full text-xs", children: new Date(notification.createdAt).toLocaleString() })
14592
+ ] }),
14593
+ /* @__PURE__ */ jsxs118("div", { className: "flex flex-row items-center", children: [
14594
+ notificationData.url ? /* @__PURE__ */ jsx183(Link2, { href: notificationData.url, children: /* @__PURE__ */ jsx183(Button, { variant: `outline`, size: `sm`, onClick: (e) => e.stopPropagation(), children: t(`foundations.notification.${notification.notificationType}.buttons.action`) }) }) : /* @__PURE__ */ jsx183(Fragment35, {}),
14595
+ !archived && /* @__PURE__ */ jsxs118(Tooltip2, { children: [
14596
+ /* @__PURE__ */ jsx183(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx183(
14597
+ Button,
14598
+ {
14599
+ variant: `link`,
14600
+ onClick: (e) => {
14601
+ e.preventDefault();
14602
+ e.stopPropagation();
14603
+ archiveNotification(notification);
14604
+ },
14605
+ className: "text-muted-foreground hover:text-destructive ml-2",
14606
+ children: /* @__PURE__ */ jsx183(ArchiveIcon, { className: "h-4 w-4 cursor-pointer" })
14607
+ }
14608
+ ) }),
14609
+ /* @__PURE__ */ jsx183(TooltipContent, { children: t(`foundations.notification.buttons.archive`) })
14610
+ ] })
14611
+ ] })
14612
+ ] }) }) }, notification.id);
14613
+ }) : /* @__PURE__ */ jsx183(LoadingSkeleton, {}) });
14614
+ }
14615
+ __name(NotificationsList, "NotificationsList");
14616
+
14617
+ // src/features/notification/components/containers/NotificationsListContainer.tsx
14618
+ import { jsx as jsx184, jsxs as jsxs119 } from "react/jsx-runtime";
14619
+ function NotificationsListContainerContent() {
14620
+ const t = useTranslations57();
14621
+ const { notifications, isLoading, error } = useNotificationContext();
14622
+ if (error) {
14623
+ return /* @__PURE__ */ jsx184("div", { className: "flex items-center justify-center p-8 text-center", children: /* @__PURE__ */ jsxs119("div", { className: "text-destructive text-sm", children: [
14624
+ /* @__PURE__ */ jsxs119("p", { children: [
14625
+ "Error loading notifications: ",
14626
+ error
14627
+ ] }),
14628
+ /* @__PURE__ */ jsx184("p", { className: "text-muted-foreground mt-2", children: "Please try refreshing the page." })
14629
+ ] }) });
14630
+ }
14631
+ const tabs = [
14632
+ {
14633
+ label: t(`foundations.notification.inbox`),
14634
+ content: /* @__PURE__ */ jsx184(NotificationsList, { archived: false })
14635
+ },
14636
+ {
14637
+ label: t(`foundations.notification.archived`),
14638
+ content: /* @__PURE__ */ jsx184(NotificationsList, { archived: true })
14639
+ }
14640
+ ];
14641
+ return /* @__PURE__ */ jsx184(TabsContainer, { tabs });
14642
+ }
14643
+ __name(NotificationsListContainerContent, "NotificationsListContainerContent");
14644
+ function NotificationsListContainer() {
14645
+ return /* @__PURE__ */ jsx184(NotificationErrorBoundary, { children: /* @__PURE__ */ jsx184(NotificationsListContainerContent, {}) });
11359
14646
  }
11360
14647
  __name(NotificationsListContainer, "NotificationsListContainer");
11361
14648
 
11362
14649
  // src/features/notification/components/modals/NotificationModal.tsx
11363
14650
  import { BellIcon } from "lucide-react";
11364
14651
  import { useTranslations as useTranslations58 } from "next-intl";
11365
- import { Fragment as Fragment29, useCallback as useCallback17, useEffect as useEffect40, useMemo as useMemo18, useRef as useRef16, useState as useState49 } from "react";
14652
+ import { Fragment as Fragment36, useCallback as useCallback19, useEffect as useEffect50, useMemo as useMemo19, useRef as useRef16, useState as useState68 } from "react";
11366
14653
  import { toast as toast10 } from "sonner";
11367
- import { jsx as jsx150, jsxs as jsxs90 } from "react/jsx-runtime";
14654
+ import { jsx as jsx185, jsxs as jsxs120 } from "react/jsx-runtime";
11368
14655
  function NotificationModalContent({ isOpen, setIsOpen }) {
11369
14656
  const instanceId = useRef16(Math.random().toString(36).substr(2, 9));
11370
14657
  const {
@@ -11382,14 +14669,14 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
11382
14669
  const { socketNotifications, removeSocketNotification, clearSocketNotifications } = useSocketContext();
11383
14670
  const t = useTranslations58();
11384
14671
  const generateUrl = usePageUrlGenerator();
11385
- const [newNotifications, setNewNotifications] = useState49(false);
14672
+ const [newNotifications, setNewNotifications] = useState68(false);
11386
14673
  const preventAutoClose = useRef16(false);
11387
14674
  const circuitBreakerRef = useRef16({
11388
14675
  count: 0,
11389
14676
  resetTime: 0,
11390
14677
  isOpen: false
11391
14678
  });
11392
- const checkCircuitBreaker = useCallback17(() => {
14679
+ const checkCircuitBreaker = useCallback19(() => {
11393
14680
  const now = Date.now();
11394
14681
  const breaker = circuitBreakerRef.current;
11395
14682
  if (now > breaker.resetTime) {
@@ -11404,21 +14691,21 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
11404
14691
  }
11405
14692
  return !breaker.isOpen;
11406
14693
  }, []);
11407
- const { unreadCount, unreadIds } = useMemo18(() => {
14694
+ const { unreadCount, unreadIds } = useMemo19(() => {
11408
14695
  const unreadNotifications2 = notifications.filter((notif) => !notif.isRead);
11409
14696
  return {
11410
14697
  unreadCount: unreadNotifications2.length,
11411
14698
  unreadIds: unreadNotifications2.map((notif) => notif.id)
11412
14699
  };
11413
14700
  }, [notifications]);
11414
- useEffect40(() => {
14701
+ useEffect50(() => {
11415
14702
  setNewNotifications(unreadCount > 0);
11416
14703
  }, [unreadCount]);
11417
- useEffect40(() => {
14704
+ useEffect50(() => {
11418
14705
  if (lastLoaded === 0) loadNotifications();
11419
14706
  }, [lastLoaded, loadNotifications]);
11420
14707
  const processSocketNotificationsRef = useRef16(null);
11421
- const processSocketNotifications = useCallback17(() => {
14708
+ const processSocketNotifications = useCallback19(() => {
11422
14709
  if (socketNotifications.length === 0) {
11423
14710
  return;
11424
14711
  }
@@ -11457,7 +14744,7 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
11457
14744
  generateUrl,
11458
14745
  checkCircuitBreaker
11459
14746
  ]);
11460
- useEffect40(() => {
14747
+ useEffect50(() => {
11461
14748
  if (processSocketNotificationsRef.current) {
11462
14749
  clearTimeout(processSocketNotificationsRef.current);
11463
14750
  }
@@ -11494,9 +14781,9 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
11494
14781
  }
11495
14782
  }, "handleOpenChange");
11496
14783
  const unreadNotifications = newNotifications && unreadCount > 0;
11497
- return /* @__PURE__ */ jsxs90(Popover, { open: isOpen, onOpenChange: handleOpenChange, "data-testid": `sidebar-notification button`, children: [
11498
- /* @__PURE__ */ jsx150(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs90(SidebarMenuButton, { className: "text-muted-foreground h-6", disabled: isLoading, children: [
11499
- /* @__PURE__ */ jsx150(
14784
+ return /* @__PURE__ */ jsxs120(Popover, { open: isOpen, onOpenChange: handleOpenChange, "data-testid": `sidebar-notification button`, children: [
14785
+ /* @__PURE__ */ jsx185(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs120(SidebarMenuButton, { className: "text-muted-foreground h-6", disabled: isLoading, children: [
14786
+ /* @__PURE__ */ jsx185(
11500
14787
  BellIcon,
11501
14788
  {
11502
14789
  className: `h-5 w-5 cursor-pointer ${unreadNotifications ? "text-destructive" : ""} ${isLoading ? "animate-pulse" : ""}`
@@ -11504,75 +14791,75 @@ function NotificationModalContent({ isOpen, setIsOpen }) {
11504
14791
  ),
11505
14792
  t(`types.notifications`, { count: 2 })
11506
14793
  ] }) }),
11507
- /* @__PURE__ */ jsx150(PopoverContent, { className: "relative left-10 w-80 border-0 p-0 shadow-none", children: /* @__PURE__ */ jsxs90(Card, { children: [
11508
- /* @__PURE__ */ jsxs90(CardHeader, { className: "p-4", children: [
11509
- /* @__PURE__ */ jsx150(CardTitle, { children: t(`types.notifications`, { count: 2 }) }),
11510
- isLoading && /* @__PURE__ */ jsx150("div", { className: "text-muted-foreground text-xs", children: "Loading..." }),
11511
- error && /* @__PURE__ */ jsxs90("div", { className: "text-destructive text-xs", children: [
14794
+ /* @__PURE__ */ jsx185(PopoverContent, { className: "relative left-10 w-80 border-0 p-0 shadow-none", children: /* @__PURE__ */ jsxs120(Card, { children: [
14795
+ /* @__PURE__ */ jsxs120(CardHeader, { className: "p-4", children: [
14796
+ /* @__PURE__ */ jsx185(CardTitle, { children: t(`types.notifications`, { count: 2 }) }),
14797
+ isLoading && /* @__PURE__ */ jsx185("div", { className: "text-muted-foreground text-xs", children: "Loading..." }),
14798
+ error && /* @__PURE__ */ jsxs120("div", { className: "text-destructive text-xs", children: [
11512
14799
  "Error: ",
11513
14800
  error
11514
14801
  ] })
11515
14802
  ] }),
11516
- /* @__PURE__ */ jsx150(Separator4, {}),
11517
- /* @__PURE__ */ jsx150(ScrollArea, { className: "h-96", children: notifications.length > 0 ? notifications.map((notification) => /* @__PURE__ */ jsx150(Fragment29, { children: generateNotification(notification, () => setIsOpen(false)) }, notification.id)) : /* @__PURE__ */ jsx150("div", { className: "p-4 text-center text-sm text-gray-500", children: t(`foundations.notification.empty`, { count: 2 }) }) })
14803
+ /* @__PURE__ */ jsx185(Separator4, {}),
14804
+ /* @__PURE__ */ jsx185(ScrollArea, { className: "h-96", children: notifications.length > 0 ? notifications.map((notification) => /* @__PURE__ */ jsx185(Fragment36, { children: generateNotification(notification, () => setIsOpen(false)) }, notification.id)) : /* @__PURE__ */ jsx185("div", { className: "p-4 text-center text-sm text-gray-500", children: t(`foundations.notification.empty`, { count: 2 }) }) })
11518
14805
  ] }) })
11519
14806
  ] });
11520
14807
  }
11521
14808
  __name(NotificationModalContent, "NotificationModalContent");
11522
14809
  function NotificationModal(props) {
11523
- return /* @__PURE__ */ jsx150(NotificationErrorBoundary, { children: /* @__PURE__ */ jsx150(NotificationModalContent, { ...props }) });
14810
+ return /* @__PURE__ */ jsx185(NotificationErrorBoundary, { children: /* @__PURE__ */ jsx185(NotificationModalContent, { ...props }) });
11524
14811
  }
11525
14812
  __name(NotificationModal, "NotificationModal");
11526
14813
 
11527
14814
  // src/features/notification/components/notifications/PushNotificationProvider.tsx
11528
- import { Fragment as Fragment30, jsx as jsx151 } from "react/jsx-runtime";
14815
+ import { Fragment as Fragment37, jsx as jsx186 } from "react/jsx-runtime";
11529
14816
  function PushNotificationProvider({ children }) {
11530
14817
  usePushNotifications();
11531
- return /* @__PURE__ */ jsx151(Fragment30, { children });
14818
+ return /* @__PURE__ */ jsx186(Fragment37, { children });
11532
14819
  }
11533
14820
  __name(PushNotificationProvider, "PushNotificationProvider");
11534
14821
 
11535
14822
  // src/features/role/components/details/RoleDetails.tsx
11536
14823
  import { useTranslations as useTranslations59 } from "next-intl";
11537
- import { jsx as jsx152 } from "react/jsx-runtime";
14824
+ import { jsx as jsx187 } from "react/jsx-runtime";
11538
14825
  function RoleDetails() {
11539
14826
  const { role } = useRoleContext();
11540
14827
  const t = useTranslations59();
11541
14828
  if (!role) return null;
11542
- return /* @__PURE__ */ jsx152(Card, { className: "w-full", children: /* @__PURE__ */ jsx152(CardContent, { className: "p-4", children: /* @__PURE__ */ jsx152(AttributeElement, { title: t(`foundations.role.fields.description.label`), value: role.description }) }) });
14829
+ return /* @__PURE__ */ jsx187(Card, { className: "w-full", children: /* @__PURE__ */ jsx187(CardContent, { className: "p-4", children: /* @__PURE__ */ jsx187(AttributeElement, { title: t(`foundations.role.fields.description.label`), value: role.description }) }) });
11543
14830
  }
11544
14831
  __name(RoleDetails, "RoleDetails");
11545
14832
 
11546
14833
  // src/features/role/components/containers/RoleContainer.tsx
11547
- import { Fragment as Fragment31, jsx as jsx153, jsxs as jsxs91 } from "react/jsx-runtime";
14834
+ import { Fragment as Fragment38, jsx as jsx188, jsxs as jsxs121 } from "react/jsx-runtime";
11548
14835
  function RoleContainer() {
11549
14836
  const { role } = useRoleContext();
11550
14837
  if (!role) return null;
11551
- return /* @__PURE__ */ jsxs91(Fragment31, { children: [
11552
- /* @__PURE__ */ jsx153(RoleDetails, {}),
11553
- /* @__PURE__ */ jsx153(RoleUsersList, { role })
14838
+ return /* @__PURE__ */ jsxs121(Fragment38, { children: [
14839
+ /* @__PURE__ */ jsx188(RoleDetails, {}),
14840
+ /* @__PURE__ */ jsx188(RoleUsersList, { role })
11554
14841
  ] });
11555
14842
  }
11556
14843
  __name(RoleContainer, "RoleContainer");
11557
14844
 
11558
14845
  // src/features/role/components/forms/FormRoles.tsx
11559
14846
  import { useTranslations as useTranslations60 } from "next-intl";
11560
- import { jsx as jsx154, jsxs as jsxs92 } from "react/jsx-runtime";
14847
+ import { jsx as jsx189, jsxs as jsxs122 } from "react/jsx-runtime";
11561
14848
  function FormRoles({ form, id, name, roles }) {
11562
14849
  const t = useTranslations60();
11563
14850
  const { hasAccesToFeature } = useCurrentUserContext();
11564
- return /* @__PURE__ */ jsx154("div", { className: "flex w-full flex-col", children: /* @__PURE__ */ jsx154(
14851
+ return /* @__PURE__ */ jsx189("div", { className: "flex w-full flex-col", children: /* @__PURE__ */ jsx189(
11565
14852
  FormField,
11566
14853
  {
11567
14854
  control: form.control,
11568
14855
  name: id,
11569
- render: ({ field }) => /* @__PURE__ */ jsxs92(FormItem, { className: `${name ? "mb-5" : "mb-1"}`, children: [
11570
- /* @__PURE__ */ jsx154(FormControl, { children: /* @__PURE__ */ jsxs92("div", { children: [
11571
- /* @__PURE__ */ jsx154("div", { className: "text-sm font-semibold", children: name }),
14856
+ render: ({ field }) => /* @__PURE__ */ jsxs122(FormItem, { className: `${name ? "mb-5" : "mb-1"}`, children: [
14857
+ /* @__PURE__ */ jsx189(FormControl, { children: /* @__PURE__ */ jsxs122("div", { children: [
14858
+ /* @__PURE__ */ jsx189("div", { className: "text-sm font-semibold", children: name }),
11572
14859
  roles.filter((role) => role.isSelectable).sort((a, b) => a.name.localeCompare(b.name)).map((role) => {
11573
14860
  if (role.requiredFeature && !hasAccesToFeature(role.requiredFeature.id)) return null;
11574
- return /* @__PURE__ */ jsxs92("div", { children: [
11575
- /* @__PURE__ */ jsx154(
14861
+ return /* @__PURE__ */ jsxs122("div", { children: [
14862
+ /* @__PURE__ */ jsx189(
11576
14863
  Checkbox,
11577
14864
  {
11578
14865
  defaultChecked: field.value.some((roleId) => roleId === role.id),
@@ -11588,14 +14875,14 @@ function FormRoles({ form, id, name, roles }) {
11588
14875
  }
11589
14876
  }
11590
14877
  ),
11591
- /* @__PURE__ */ jsxs92(Tooltip2, { children: [
11592
- /* @__PURE__ */ jsx154(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx154(FormLabel, { className: "ml-3 font-normal", children: t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) }) }) }),
11593
- /* @__PURE__ */ jsx154(TooltipContent, { children: t(`foundations.role.roles_descriptions`, { role: role.id.replaceAll(`-`, ``) }) })
14878
+ /* @__PURE__ */ jsxs122(Tooltip2, { children: [
14879
+ /* @__PURE__ */ jsx189(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx189(FormLabel, { className: "ml-3 font-normal", children: t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) }) }) }),
14880
+ /* @__PURE__ */ jsx189(TooltipContent, { children: t(`foundations.role.roles_descriptions`, { role: role.id.replaceAll(`-`, ``) }) })
11594
14881
  ] })
11595
14882
  ] }, role.id);
11596
14883
  })
11597
14884
  ] }) }),
11598
- /* @__PURE__ */ jsx154(FormMessage, {})
14885
+ /* @__PURE__ */ jsx189(FormMessage, {})
11599
14886
  ] })
11600
14887
  }
11601
14888
  ) });
@@ -11604,13 +14891,13 @@ __name(FormRoles, "FormRoles");
11604
14891
 
11605
14892
  // src/features/role/components/forms/RemoveUserFromRole.tsx
11606
14893
  import { useTranslations as useTranslations61 } from "next-intl";
11607
- import { useEffect as useEffect41, useState as useState50 } from "react";
11608
- import { Fragment as Fragment32, jsx as jsx155, jsxs as jsxs93 } from "react/jsx-runtime";
14894
+ import { useEffect as useEffect51, useState as useState69 } from "react";
14895
+ import { Fragment as Fragment39, jsx as jsx190, jsxs as jsxs123 } from "react/jsx-runtime";
11609
14896
  function RemoveUserFromRole({ role, user, refresh }) {
11610
- const [open, setOpen] = useState50(false);
11611
- const [canRemove, setCanRemove] = useState50(false);
14897
+ const [open, setOpen] = useState69(false);
14898
+ const [canRemove, setCanRemove] = useState69(false);
11612
14899
  const t = useTranslations61();
11613
- useEffect41(() => {
14900
+ useEffect51(() => {
11614
14901
  async function checkCompanyAdminDeletability() {
11615
14902
  const roleUsers = await UserService.findAllUsersByRole({
11616
14903
  roleId: role.id
@@ -11637,8 +14924,8 @@ function RemoveUserFromRole({ role, user, refresh }) {
11637
14924
  }
11638
14925
  }, "remove");
11639
14926
  const roleName = t(`foundations.role.roles`, { role: role.id.replaceAll(`-`, ``) });
11640
- return /* @__PURE__ */ jsxs93(Dialog, { open, onOpenChange: setOpen, children: [
11641
- /* @__PURE__ */ jsx155(
14927
+ return /* @__PURE__ */ jsxs123(Dialog, { open, onOpenChange: setOpen, children: [
14928
+ /* @__PURE__ */ jsx190(
11642
14929
  DialogTrigger,
11643
14930
  {
11644
14931
  onClick: (e) => {
@@ -11646,19 +14933,19 @@ function RemoveUserFromRole({ role, user, refresh }) {
11646
14933
  e.preventDefault();
11647
14934
  setOpen(true);
11648
14935
  },
11649
- children: /* @__PURE__ */ jsx155("span", { className: "hover:text-destructive cursor-pointer", children: t(`foundations.role.remove_user.title`) })
14936
+ children: /* @__PURE__ */ jsx190("span", { className: "hover:text-destructive cursor-pointer", children: t(`foundations.role.remove_user.title`) })
11650
14937
  }
11651
14938
  ),
11652
- /* @__PURE__ */ jsxs93(DialogContent, { className: `flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`, children: [
11653
- /* @__PURE__ */ jsxs93(DialogHeader, { children: [
11654
- /* @__PURE__ */ jsx155(DialogTitle, { children: t(`foundations.role.remove_user.title`) }),
11655
- /* @__PURE__ */ jsx155(DialogDescription, { children: canRemove ? t(`foundations.role.remove_user.subtitle_allowed`) : t(`foundations.role.remove_user.subtitle_not_allowed`) })
14939
+ /* @__PURE__ */ jsxs123(DialogContent, { className: `flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`, children: [
14940
+ /* @__PURE__ */ jsxs123(DialogHeader, { children: [
14941
+ /* @__PURE__ */ jsx190(DialogTitle, { children: t(`foundations.role.remove_user.title`) }),
14942
+ /* @__PURE__ */ jsx190(DialogDescription, { children: canRemove ? t(`foundations.role.remove_user.subtitle_allowed`) : t(`foundations.role.remove_user.subtitle_not_allowed`) })
11656
14943
  ] }),
11657
- canRemove ? /* @__PURE__ */ jsxs93(Fragment32, { children: [
14944
+ canRemove ? /* @__PURE__ */ jsxs123(Fragment39, { children: [
11658
14945
  t(`foundations.role.remove_user.description_allowed`, { role: roleName, user: user.name }),
11659
- /* @__PURE__ */ jsxs93("div", { className: "flex justify-end", children: [
11660
- /* @__PURE__ */ jsx155(Button, { className: "mr-2", variant: "outline", type: `button`, onClick: () => setOpen(false), children: t(`generic.buttons.cancel`) }),
11661
- /* @__PURE__ */ jsx155(
14946
+ /* @__PURE__ */ jsxs123("div", { className: "flex justify-end", children: [
14947
+ /* @__PURE__ */ jsx190(Button, { className: "mr-2", variant: "outline", type: `button`, onClick: () => setOpen(false), children: t(`generic.buttons.cancel`) }),
14948
+ /* @__PURE__ */ jsx190(
11662
14949
  Button,
11663
14950
  {
11664
14951
  type: "submit",
@@ -11671,7 +14958,7 @@ function RemoveUserFromRole({ role, user, refresh }) {
11671
14958
  }
11672
14959
  )
11673
14960
  ] })
11674
- ] }) : /* @__PURE__ */ jsx155(Fragment32, { children: t(`foundations.role.remove_user.description_not_allowed`, { role: roleName, user: user.name }) })
14961
+ ] }) : /* @__PURE__ */ jsx190(Fragment39, { children: t(`foundations.role.remove_user.description_not_allowed`, { role: roleName, user: user.name }) })
11675
14962
  ] })
11676
14963
  ] });
11677
14964
  }
@@ -11680,14 +14967,14 @@ __name(RemoveUserFromRole, "RemoveUserFromRole");
11680
14967
  // src/features/role/components/forms/UserRoleAdd.tsx
11681
14968
  import { PlusCircle } from "lucide-react";
11682
14969
  import { useTranslations as useTranslations62 } from "next-intl";
11683
- import { useCallback as useCallback18, useEffect as useEffect42, useRef as useRef17, useState as useState51 } from "react";
14970
+ import { useCallback as useCallback20, useEffect as useEffect52, useRef as useRef17, useState as useState70 } from "react";
11684
14971
  import { toast as toast11 } from "sonner";
11685
- import { Fragment as Fragment33, jsx as jsx156, jsxs as jsxs94 } from "react/jsx-runtime";
14972
+ import { Fragment as Fragment40, jsx as jsx191, jsxs as jsxs124 } from "react/jsx-runtime";
11686
14973
  function UserRoleAdd({ user, refresh }) {
11687
- const [open, setOpen] = useState51(false);
14974
+ const [open, setOpen] = useState70(false);
11688
14975
  const inputRef = useRef17(null);
11689
- const [searchTerm, setSearchTerm] = useState51("");
11690
- const [roles, setRoles] = useState51([]);
14976
+ const [searchTerm, setSearchTerm] = useState70("");
14977
+ const [roles, setRoles] = useState70([]);
11691
14978
  const t = useTranslations62();
11692
14979
  const addUserToRole = /* @__PURE__ */ __name(async (role) => {
11693
14980
  await RoleService.addUserToRole({
@@ -11711,7 +14998,7 @@ function UserRoleAdd({ user, refresh }) {
11711
14998
  );
11712
14999
  refresh();
11713
15000
  }, "addUserToRole");
11714
- const searchRoles = useCallback18(
15001
+ const searchRoles = useCallback20(
11715
15002
  async (term) => {
11716
15003
  setRoles(
11717
15004
  await RoleService.findAllRolesUserNotIn({
@@ -11723,32 +15010,32 @@ function UserRoleAdd({ user, refresh }) {
11723
15010
  [searchTerm, user]
11724
15011
  );
11725
15012
  const updateSearchTerm = useDebounce(searchRoles, 500);
11726
- useEffect42(() => {
15013
+ useEffect52(() => {
11727
15014
  if (open) updateSearchTerm(searchTerm);
11728
15015
  }, [open, searchTerm]);
11729
- useEffect42(() => {
15016
+ useEffect52(() => {
11730
15017
  if (open) searchRoles("");
11731
15018
  }, [open]);
11732
- return /* @__PURE__ */ jsxs94(Fragment33, { children: [
11733
- /* @__PURE__ */ jsxs94(Button, { size: "sm", onClick: () => setOpen(true), children: [
11734
- /* @__PURE__ */ jsx156(PlusCircle, { className: "mr-3 h-3.5 w-3.5" }),
15019
+ return /* @__PURE__ */ jsxs124(Fragment40, { children: [
15020
+ /* @__PURE__ */ jsxs124(Button, { size: "sm", onClick: () => setOpen(true), children: [
15021
+ /* @__PURE__ */ jsx191(PlusCircle, { className: "mr-3 h-3.5 w-3.5" }),
11735
15022
  t(`generic.association.label`, {
11736
15023
  source: t(`types.roles`, { count: 1 }),
11737
15024
  destination: t(`types.users`, { count: 1 })
11738
15025
  })
11739
15026
  ] }),
11740
- /* @__PURE__ */ jsxs94(CommandDialog, { open, onOpenChange: setOpen, children: [
11741
- /* @__PURE__ */ jsx156(DialogTitle, { children: t(`generic.association.label`, {
15027
+ /* @__PURE__ */ jsxs124(CommandDialog, { open, onOpenChange: setOpen, children: [
15028
+ /* @__PURE__ */ jsx191(DialogTitle, { children: t(`generic.association.label`, {
11742
15029
  source: t(`types.roles`, { count: 1 }),
11743
15030
  destination: t(`types.users`, { count: 1 })
11744
15031
  }) }),
11745
- /* @__PURE__ */ jsx156(DialogDescription, { children: t(`generic.association.description`, {
15032
+ /* @__PURE__ */ jsx191(DialogDescription, { children: t(`generic.association.description`, {
11746
15033
  source: t(`types.roles`, { count: 1 }),
11747
15034
  destination: t(`types.users`, { count: 1 }),
11748
15035
  destination_name: user.name
11749
15036
  }) }),
11750
- /* @__PURE__ */ jsxs94(Command, { shouldFilter: false, children: [
11751
- /* @__PURE__ */ jsx156(
15037
+ /* @__PURE__ */ jsxs124(Command, { shouldFilter: false, children: [
15038
+ /* @__PURE__ */ jsx191(
11752
15039
  CommandInput,
11753
15040
  {
11754
15041
  placeholder: t(`generic.search.placeholder`, { type: t(`types.roles`, { count: 1 }) }),
@@ -11757,9 +15044,9 @@ function UserRoleAdd({ user, refresh }) {
11757
15044
  ref: inputRef
11758
15045
  }
11759
15046
  ),
11760
- /* @__PURE__ */ jsxs94(CommandList, { className: "mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-x-hidden overflow-y-auto", children: [
11761
- /* @__PURE__ */ jsx156(CommandEmpty, { children: t(`generic.search.no_results`, { type: t(`types.roles`, { count: 1 }) }) }),
11762
- roles.map((role) => /* @__PURE__ */ jsx156(
15047
+ /* @__PURE__ */ jsxs124(CommandList, { className: "mt-3 h-auto max-h-96 min-h-96 max-w-full overflow-x-hidden overflow-y-auto", children: [
15048
+ /* @__PURE__ */ jsx191(CommandEmpty, { children: t(`generic.search.no_results`, { type: t(`types.roles`, { count: 1 }) }) }),
15049
+ roles.map((role) => /* @__PURE__ */ jsx191(
11763
15050
  CommandItem,
11764
15051
  {
11765
15052
  className: "cursor-pointer",
@@ -11778,7 +15065,7 @@ __name(UserRoleAdd, "UserRoleAdd");
11778
15065
 
11779
15066
  // src/features/role/components/lists/RolesList.tsx
11780
15067
  import { useTranslations as useTranslations63 } from "next-intl";
11781
- import { jsx as jsx157 } from "react/jsx-runtime";
15068
+ import { jsx as jsx192 } from "react/jsx-runtime";
11782
15069
  function RolesList() {
11783
15070
  const t = useTranslations63();
11784
15071
  const data = useDataListRetriever({
@@ -11786,7 +15073,7 @@ function RolesList() {
11786
15073
  retrieverParams: {},
11787
15074
  module: Modules.Role
11788
15075
  });
11789
- return /* @__PURE__ */ jsx157(
15076
+ return /* @__PURE__ */ jsx192(
11790
15077
  ContentListTable,
11791
15078
  {
11792
15079
  data,
@@ -11800,7 +15087,7 @@ __name(RolesList, "RolesList");
11800
15087
 
11801
15088
  // src/features/role/components/lists/UserRolesList.tsx
11802
15089
  import { useTranslations as useTranslations64 } from "next-intl";
11803
- import { jsx as jsx158 } from "react/jsx-runtime";
15090
+ import { jsx as jsx193 } from "react/jsx-runtime";
11804
15091
  function UserRolesList({ user }) {
11805
15092
  const t = useTranslations64();
11806
15093
  const data = useDataListRetriever({
@@ -11808,7 +15095,7 @@ function UserRolesList({ user }) {
11808
15095
  retrieverParams: { userId: user.id },
11809
15096
  module: Modules.Role
11810
15097
  });
11811
- return /* @__PURE__ */ jsx158(
15098
+ return /* @__PURE__ */ jsx193(
11812
15099
  ContentListTable,
11813
15100
  {
11814
15101
  data,
@@ -12146,6 +15433,45 @@ export {
12146
15433
  Logout,
12147
15434
  RefreshUser,
12148
15435
  ResetPassword,
15436
+ SubscriptionSummaryCard,
15437
+ PaymentMethodSummaryCard,
15438
+ CustomerInfoCard,
15439
+ InvoicesSummaryCard,
15440
+ BillingUsageSummaryCard,
15441
+ PaymentMethodEditor,
15442
+ PaymentMethodCard,
15443
+ PaymentMethodsList,
15444
+ PaymentMethodsContainer,
15445
+ formatInterval,
15446
+ formatCurrency,
15447
+ formatDate3 as formatDate,
15448
+ InvoiceStatusBadge,
15449
+ InvoiceDetails,
15450
+ InvoicesList,
15451
+ InvoicesContainer,
15452
+ CancelSubscriptionDialog,
15453
+ PricingCard,
15454
+ PricingCardsGrid,
15455
+ ProrationPreview,
15456
+ SubscriptionEditor,
15457
+ SubscriptionStatusBadge,
15458
+ SubscriptionDetails,
15459
+ SubscriptionsList,
15460
+ SubscriptionsContainer,
15461
+ UsageSummaryCard,
15462
+ UsageSummaryCards,
15463
+ UsageContainer,
15464
+ UsageHistoryTable,
15465
+ BillingDetailModal,
15466
+ BillingAlertBanner,
15467
+ BillingDashboardContainer,
15468
+ StripeProvider,
15469
+ isStripeConfigured,
15470
+ PriceEditor,
15471
+ PricesList,
15472
+ ProductEditor,
15473
+ ProductsList,
15474
+ ProductsAdminContainer,
12149
15475
  CompanyDetails,
12150
15476
  AdminCompanyContainer,
12151
15477
  CompanyContainer,
@@ -12201,4 +15527,4 @@ export {
12201
15527
  useUserTableStructure,
12202
15528
  useContentTableStructure
12203
15529
  };
12204
- //# sourceMappingURL=chunk-2FCG3K64.mjs.map
15530
+ //# sourceMappingURL=chunk-5RAUCUAA.mjs.map