@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
@@ -0,0 +1,109 @@
1
+ "use client";
2
+
3
+ import { Activity } from "lucide-react";
4
+ import { useEffect, useState } from "react";
5
+ import { StripeSubscriptionInterface, StripeSubscriptionService } from "../../../stripe-subscription";
6
+ import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
7
+ import { StripeUsageService } from "../../data/stripe-usage.service";
8
+ import { UsageSummaryCards } from "../widgets/UsageSummaryCards";
9
+
10
+ export function UsageContainer() {
11
+ const [meters, setMeters] = useState<MeterInterface[]>([]);
12
+ const [summaries, setSummaries] = useState<Record<string, MeterSummaryInterface | null>>({});
13
+ const [loading, setLoading] = useState<boolean>(true);
14
+ const [subscriptions, setSubscriptions] = useState<StripeSubscriptionInterface[]>([]);
15
+
16
+ useEffect(() => {
17
+ loadUsageData();
18
+ }, []);
19
+
20
+ const loadUsageData = async () => {
21
+ setLoading(true);
22
+
23
+ try {
24
+ // First, check if there are any metered subscriptions
25
+ const fetchedSubscriptions = await StripeSubscriptionService.listSubscriptions();
26
+ setSubscriptions(fetchedSubscriptions);
27
+
28
+ const hasMeteredSubscriptions = fetchedSubscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
29
+
30
+ if (!hasMeteredSubscriptions) {
31
+ setLoading(false);
32
+ return;
33
+ }
34
+
35
+ // Load meters
36
+ const fetchedMeters = await StripeUsageService.listMeters();
37
+ setMeters(fetchedMeters);
38
+
39
+ // Load summaries for each meter (current month)
40
+ const summariesMap: Record<string, MeterSummaryInterface | null> = {};
41
+ const now = new Date();
42
+ const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
43
+ const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0, 23, 59, 59, 999);
44
+
45
+ for (const meter of fetchedMeters) {
46
+ try {
47
+ const meterSummaries = await StripeUsageService.getMeterSummaries({
48
+ meterId: meter.id,
49
+ startTime: startOfMonth,
50
+ endTime: endOfMonth,
51
+ });
52
+ // Use the first (most recent) summary
53
+ summariesMap[meter.id] = meterSummaries.length > 0 ? meterSummaries[0] : null;
54
+ } catch (error) {
55
+ console.error(`[UsageContainer] Failed to load summaries for meter ${meter.id}:`, error);
56
+ summariesMap[meter.id] = null;
57
+ }
58
+ }
59
+
60
+ setSummaries(summariesMap);
61
+ } catch (error) {
62
+ console.error("[UsageContainer] Failed to load usage data:", error);
63
+ } finally {
64
+ setLoading(false);
65
+ }
66
+ };
67
+
68
+ // Check if there are any metered subscriptions
69
+ const hasMeteredSubscriptions = subscriptions.some((sub) => sub.price?.recurring?.usageType === "metered");
70
+
71
+ // Don't render if no metered subscriptions
72
+ if (!loading && !hasMeteredSubscriptions) {
73
+ return null;
74
+ }
75
+
76
+ if (loading) {
77
+ return (
78
+ <div className="flex h-64 items-center justify-center">
79
+ <p className="text-muted-foreground">Loading usage data...</p>
80
+ </div>
81
+ );
82
+ }
83
+
84
+ return (
85
+ <div className="flex w-full flex-col gap-y-6">
86
+ {/* Header */}
87
+ <div className="flex items-center gap-x-3">
88
+ <Activity className="h-8 w-8" />
89
+ <h1 className="text-3xl font-bold">Usage Tracking</h1>
90
+ </div>
91
+
92
+ {/* Empty State */}
93
+ {meters.length === 0 && (
94
+ <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">
95
+ <Activity className="text-muted-foreground h-16 w-16" />
96
+ <div className="text-center">
97
+ <h3 className="mb-2 text-xl font-semibold">No usage meters configured</h3>
98
+ <p className="text-muted-foreground">
99
+ Usage tracking will appear here when you have metered subscriptions with configured meters.
100
+ </p>
101
+ </div>
102
+ </div>
103
+ )}
104
+
105
+ {/* Usage Summary Cards */}
106
+ {meters.length > 0 && <UsageSummaryCards meters={meters} summaries={summaries} />}
107
+ </div>
108
+ );
109
+ }
@@ -0,0 +1 @@
1
+ export * from "./UsageContainer";
@@ -0,0 +1,90 @@
1
+ "use client";
2
+
3
+ import { Activity } from "lucide-react";
4
+ import { Card, CardContent, CardHeader } from "../../../../../shadcnui";
5
+ import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
6
+
7
+ type UsageSummaryCardProps = {
8
+ meter: MeterInterface;
9
+ summary: MeterSummaryInterface | null;
10
+ };
11
+
12
+ /**
13
+ * Get progress bar color based on usage percentage
14
+ */
15
+ function getProgressColor(percentage: number | null): string {
16
+ if (percentage === null) return "bg-blue-500";
17
+ if (percentage >= 90) return "bg-red-500";
18
+ if (percentage >= 75) return "bg-orange-500";
19
+ return "bg-green-500";
20
+ }
21
+
22
+ /**
23
+ * Format a Unix timestamp to readable date
24
+ */
25
+ function formatDate(date: Date | undefined): string {
26
+ if (!date) return "N/A";
27
+
28
+ try {
29
+ return new Intl.DateTimeFormat("en-US", {
30
+ month: "short",
31
+ day: "numeric",
32
+ }).format(new Date(date));
33
+ } catch (error) {
34
+ return "Invalid Date";
35
+ }
36
+ }
37
+
38
+ export function UsageSummaryCard({ meter, summary }: UsageSummaryCardProps) {
39
+ const currentUsage = summary?.aggregatedValue ?? 0;
40
+ const limit = (meter as any).limit; // Meters may have optional limit field
41
+ const percentage = limit && limit > 0 ? (currentUsage / limit) * 100 : null;
42
+ const progressColor = getProgressColor(percentage);
43
+ const progressWidth = percentage !== null ? Math.min(percentage, 100) : 0;
44
+
45
+ const displayName = meter.displayName || meter.eventName;
46
+ const hasLimit = limit !== null && limit !== undefined;
47
+
48
+ return (
49
+ <Card>
50
+ <CardHeader className="flex flex-row items-center gap-x-3 pb-3">
51
+ <div className="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600">
52
+ <Activity className="h-5 w-5" />
53
+ </div>
54
+ <div className="flex flex-col">
55
+ <h3 className="font-semibold">{displayName}</h3>
56
+ <p className="text-xs text-gray-500">{meter.id}</p>
57
+ </div>
58
+ </CardHeader>
59
+
60
+ <CardContent className="flex flex-col gap-y-4">
61
+ {/* Current Usage */}
62
+ <div>
63
+ <p className="text-3xl font-bold">{currentUsage.toLocaleString()}</p>
64
+ {hasLimit && <p className="text-sm text-gray-500">of {limit.toLocaleString()} used</p>}
65
+ </div>
66
+
67
+ {/* Progress Bar */}
68
+ {hasLimit ? (
69
+ <div className="flex flex-col gap-y-2">
70
+ <div className="h-2 w-full overflow-hidden rounded-full bg-gray-200">
71
+ <div className={`h-full transition-all ${progressColor}`} style={{ width: `${progressWidth}%` }} />
72
+ </div>
73
+ <p className="text-sm text-gray-500">{percentage?.toFixed(1)}% used</p>
74
+ </div>
75
+ ) : (
76
+ <p className="text-sm text-gray-500">No limit set</p>
77
+ )}
78
+
79
+ {/* Period Information */}
80
+ {summary && summary.start && summary.end && (
81
+ <div className="border-t pt-3">
82
+ <p className="text-xs text-gray-500">
83
+ Period: {formatDate(summary.start)} - {formatDate(summary.end)}
84
+ </p>
85
+ </div>
86
+ )}
87
+ </CardContent>
88
+ </Card>
89
+ );
90
+ }
@@ -0,0 +1 @@
1
+ export * from "./UsageSummaryCard";
@@ -0,0 +1,4 @@
1
+ export * from "./containers";
2
+ export * from "./details";
3
+ export * from "./lists";
4
+ export * from "./widgets";
@@ -0,0 +1,72 @@
1
+ "use client";
2
+
3
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../../../../../shadcnui";
4
+ import { StripeUsageInterface } from "../../data/stripe-usage.interface";
5
+
6
+ type UsageHistoryTableProps = {
7
+ usageRecords: StripeUsageInterface[];
8
+ };
9
+
10
+ /**
11
+ * Format a date with time for usage history
12
+ */
13
+ function formatDateTime(date: Date | string | undefined): string {
14
+ if (!date) return "N/A";
15
+
16
+ const dateObj = typeof date === "string" ? new Date(date) : date;
17
+
18
+ try {
19
+ return new Intl.DateTimeFormat("en-US", {
20
+ month: "short",
21
+ day: "numeric",
22
+ year: "numeric",
23
+ hour: "numeric",
24
+ minute: "2-digit",
25
+ }).format(dateObj);
26
+ } catch (error) {
27
+ return "Invalid Date";
28
+ }
29
+ }
30
+
31
+ export function UsageHistoryTable({ usageRecords }: UsageHistoryTableProps) {
32
+ if (usageRecords.length === 0) {
33
+ return (
34
+ <div className="rounded-lg border p-8 text-center">
35
+ <p className="text-muted-foreground">No usage history available.</p>
36
+ </div>
37
+ );
38
+ }
39
+
40
+ return (
41
+ <div className="flex w-full flex-col gap-y-4">
42
+ <h2 className="text-xl font-semibold">Usage History</h2>
43
+ <div className="overflow-hidden rounded-lg border">
44
+ <Table>
45
+ <TableHeader className="bg-muted">
46
+ <TableRow>
47
+ <TableHead>Date & Time</TableHead>
48
+ <TableHead>Meter Event</TableHead>
49
+ <TableHead className="text-right">Quantity</TableHead>
50
+ <TableHead>Event ID</TableHead>
51
+ </TableRow>
52
+ </TableHeader>
53
+ <TableBody>
54
+ {usageRecords.map((record) => {
55
+ const dateTime = formatDateTime(record.timestamp);
56
+ const quantity = record.quantity.toLocaleString();
57
+
58
+ return (
59
+ <TableRow key={record.id}>
60
+ <TableCell className="font-medium">{dateTime}</TableCell>
61
+ <TableCell className="text-muted-foreground">{record.meterEventName}</TableCell>
62
+ <TableCell className="text-right font-medium">{quantity}</TableCell>
63
+ <TableCell className="text-muted-foreground text-sm font-mono">{record.stripeEventId}</TableCell>
64
+ </TableRow>
65
+ );
66
+ })}
67
+ </TableBody>
68
+ </Table>
69
+ </div>
70
+ </div>
71
+ );
72
+ }
@@ -0,0 +1 @@
1
+ export * from "./UsageHistoryTable";
@@ -0,0 +1,19 @@
1
+ "use client";
2
+
3
+ import { MeterInterface, MeterSummaryInterface } from "../../data/stripe-usage.interface";
4
+ import { UsageSummaryCard } from "../details/UsageSummaryCard";
5
+
6
+ type UsageSummaryCardsProps = {
7
+ meters: MeterInterface[];
8
+ summaries: Record<string, MeterSummaryInterface | null>;
9
+ };
10
+
11
+ export function UsageSummaryCards({ meters, summaries }: UsageSummaryCardsProps) {
12
+ return (
13
+ <div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
14
+ {meters.map((meter) => (
15
+ <UsageSummaryCard key={meter.id} meter={meter} summary={summaries[meter.id] || null} />
16
+ ))}
17
+ </div>
18
+ );
19
+ }
@@ -0,0 +1 @@
1
+ export * from "./UsageSummaryCards";
@@ -0,0 +1,3 @@
1
+ export * from "./stripe-usage";
2
+ export * from "./stripe-usage.interface";
3
+ export * from "./stripe-usage.service";
@@ -0,0 +1,55 @@
1
+ import { ApiDataInterface } from "../../../../core";
2
+
3
+ // ============================================================================
4
+ // Usage Record Interfaces
5
+ // ============================================================================
6
+
7
+ export interface StripeUsageInterface extends ApiDataInterface {
8
+ get subscriptionId(): string;
9
+ get meterId(): string;
10
+ get meterEventName(): string;
11
+ get stripeEventId(): string;
12
+ get quantity(): number;
13
+ get timestamp(): Date | undefined;
14
+ }
15
+
16
+ // ============================================================================
17
+ // Meter Interfaces
18
+ // ============================================================================
19
+
20
+ export interface MeterInterface {
21
+ id: string;
22
+ displayName: string;
23
+ eventName: string;
24
+ status: string;
25
+ }
26
+
27
+ export interface MeterSummaryInterface {
28
+ meterId: string;
29
+ start: Date;
30
+ end: Date;
31
+ aggregatedValue: number;
32
+ }
33
+
34
+ export interface UsageSummaryInterface {
35
+ subscriptionItemId: string;
36
+ period: {
37
+ start: Date;
38
+ end: Date;
39
+ };
40
+ totalUsage: number;
41
+ }
42
+
43
+ // ============================================================================
44
+ // Usage Input DTOs
45
+ // ============================================================================
46
+
47
+ export type ReportUsageInput = {
48
+ subscriptionItemId: string;
49
+ quantity: number;
50
+ timestamp?: number;
51
+ action?: "increment" | "set";
52
+ };
53
+
54
+ // Backwards compatibility alias
55
+ export type UsageRecordInterface = StripeUsageInterface;
@@ -0,0 +1,129 @@
1
+ import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef, PreviousRef } from "../../../../core";
2
+ import {
3
+ MeterInterface,
4
+ MeterSummaryInterface,
5
+ ReportUsageInput,
6
+ StripeUsageInterface,
7
+ UsageSummaryInterface,
8
+ } from "./stripe-usage.interface";
9
+
10
+ /**
11
+ * Service for managing Stripe usage tracking
12
+ */
13
+ export class StripeUsageService extends AbstractService {
14
+ // ============================================================================
15
+ // Meter Methods
16
+ // ============================================================================
17
+
18
+ /**
19
+ * List all available usage meters
20
+ */
21
+ static async listMeters(params?: { next?: NextRef; prev?: PreviousRef }): Promise<MeterInterface[]> {
22
+ const endpoint = new EndpointCreator({
23
+ endpoint: Modules.StripeUsage,
24
+ childEndpoint: "meters",
25
+ });
26
+
27
+ return this.callApi({
28
+ type: Modules.StripeUsage,
29
+ method: HttpMethod.GET,
30
+ endpoint: endpoint.generate(),
31
+ next: params?.next,
32
+ previous: params?.prev,
33
+ });
34
+ }
35
+
36
+ /**
37
+ * Get meter summaries for a specific time period
38
+ */
39
+ static async getMeterSummaries(params: {
40
+ meterId: string;
41
+ startTime: Date;
42
+ endTime: Date;
43
+ }): Promise<MeterSummaryInterface[]> {
44
+ const endpoint = new EndpointCreator({
45
+ endpoint: Modules.StripeUsage,
46
+ childEndpoint: `meters/${params.meterId}/summaries`,
47
+ });
48
+
49
+ endpoint.addAdditionalParam("startTime", params.startTime.toISOString());
50
+ endpoint.addAdditionalParam("endTime", params.endTime.toISOString());
51
+
52
+ return this.callApi({
53
+ type: Modules.StripeUsage,
54
+ method: HttpMethod.GET,
55
+ endpoint: endpoint.generate(),
56
+ });
57
+ }
58
+
59
+ // ============================================================================
60
+ // Usage Record Methods
61
+ // ============================================================================
62
+
63
+ /**
64
+ * Report usage for a subscription item
65
+ */
66
+ static async reportUsage(params: ReportUsageInput): Promise<StripeUsageInterface> {
67
+ const endpoint = new EndpointCreator({
68
+ endpoint: Modules.StripeUsage,
69
+ });
70
+
71
+ return this.callApi<StripeUsageInterface>({
72
+ type: Modules.StripeUsage,
73
+ method: HttpMethod.POST,
74
+ endpoint: endpoint.generate(),
75
+ input: params,
76
+ });
77
+ }
78
+
79
+ /**
80
+ * List usage records for a subscription item
81
+ */
82
+ static async listUsageRecords(params: {
83
+ subscriptionItemId: string;
84
+ next?: NextRef;
85
+ prev?: PreviousRef;
86
+ }): Promise<StripeUsageInterface[]> {
87
+ const endpoint = new EndpointCreator({
88
+ endpoint: Modules.StripeUsage,
89
+ });
90
+
91
+ endpoint.addAdditionalParam("subscriptionItemId", params.subscriptionItemId);
92
+
93
+ return this.callApi({
94
+ type: Modules.StripeUsage,
95
+ method: HttpMethod.GET,
96
+ endpoint: endpoint.generate(),
97
+ next: params?.next,
98
+ previous: params?.prev,
99
+ });
100
+ }
101
+
102
+ /**
103
+ * Get usage summary for a subscription item
104
+ */
105
+ static async getUsageSummary(params: {
106
+ subscriptionItemId: string;
107
+ start?: Date;
108
+ end?: Date;
109
+ }): Promise<UsageSummaryInterface> {
110
+ const endpoint = new EndpointCreator({
111
+ endpoint: Modules.StripeUsage,
112
+ childEndpoint: "summary",
113
+ });
114
+
115
+ endpoint.addAdditionalParam("subscriptionItemId", params.subscriptionItemId);
116
+ if (params.start) {
117
+ endpoint.addAdditionalParam("start", params.start.toISOString());
118
+ }
119
+ if (params.end) {
120
+ endpoint.addAdditionalParam("end", params.end.toISOString());
121
+ }
122
+
123
+ return this.callApi({
124
+ type: Modules.StripeUsage,
125
+ method: HttpMethod.GET,
126
+ endpoint: endpoint.generate(),
127
+ });
128
+ }
129
+ }
@@ -0,0 +1,70 @@
1
+ import { AbstractApiData, JsonApiHydratedDataInterface, Modules } from "../../../../core";
2
+ import { ReportUsageInput, StripeUsageInterface } from "./stripe-usage.interface";
3
+
4
+ export class StripeUsage extends AbstractApiData implements StripeUsageInterface {
5
+ private _subscriptionId?: string;
6
+ private _meterId?: string;
7
+ private _meterEventName?: string;
8
+ private _stripeEventId?: string;
9
+ private _quantity?: number;
10
+ private _timestamp?: Date;
11
+
12
+ get subscriptionId(): string {
13
+ if (!this._subscriptionId) throw new Error("subscriptionId is not defined");
14
+ return this._subscriptionId;
15
+ }
16
+
17
+ get meterId(): string {
18
+ if (!this._meterId) throw new Error("meterId is not defined");
19
+ return this._meterId;
20
+ }
21
+
22
+ get meterEventName(): string {
23
+ if (!this._meterEventName) throw new Error("meterEventName is not defined");
24
+ return this._meterEventName;
25
+ }
26
+
27
+ get stripeEventId(): string {
28
+ if (!this._stripeEventId) throw new Error("stripeEventId is not defined");
29
+ return this._stripeEventId;
30
+ }
31
+
32
+ get quantity(): number {
33
+ if (this._quantity === undefined) throw new Error("quantity is not defined");
34
+ return this._quantity;
35
+ }
36
+
37
+ get timestamp(): Date | undefined {
38
+ return this._timestamp;
39
+ }
40
+
41
+ rehydrate(data: JsonApiHydratedDataInterface): this {
42
+ super.rehydrate(data);
43
+
44
+ this._subscriptionId = data.jsonApi.attributes.subscriptionId;
45
+ this._meterId = data.jsonApi.attributes.meterId;
46
+ this._meterEventName = data.jsonApi.attributes.meterEventName;
47
+ this._stripeEventId = data.jsonApi.attributes.stripeEventId;
48
+ this._quantity = data.jsonApi.attributes.quantity;
49
+ this._timestamp = data.jsonApi.attributes.timestamp ? new Date(data.jsonApi.attributes.timestamp) : undefined;
50
+
51
+ return this;
52
+ }
53
+
54
+ createJsonApi(data: ReportUsageInput): any {
55
+ const response: any = {
56
+ data: {
57
+ type: Modules.StripeUsage.name,
58
+ attributes: {
59
+ subscriptionItemId: data.subscriptionItemId,
60
+ quantity: data.quantity,
61
+ },
62
+ },
63
+ };
64
+
65
+ if (data.timestamp !== undefined) response.data.attributes.timestamp = data.timestamp;
66
+ if (data.action !== undefined) response.data.attributes.action = data.action;
67
+
68
+ return response;
69
+ }
70
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./data";
2
+ export * from "./stripe-usage.module";
@@ -0,0 +1,9 @@
1
+ import { ModuleFactory } from "../../../permissions";
2
+ import { StripeUsage } from "./data/stripe-usage";
3
+
4
+ export const StripeUsageModule = (factory: ModuleFactory) =>
5
+ factory({
6
+ name: "stripe-usage-records",
7
+ model: StripeUsage,
8
+ moduleId: "c2e9f4a6-1d7b-4e3a-8f5c-9b2d6a1e7f3c",
9
+ });
@@ -26,8 +26,8 @@ import { useI18nRouter } from "../../../../i18n";
26
26
  import { getRoleId } from "../../../../roles";
27
27
  import { Dialog, DialogContent, Form, ScrollArea } from "../../../../shadcnui";
28
28
  import { FeatureInterface } from "../../../feature";
29
- import { S3Interface } from "../../../s3";
30
29
  import { FeatureService } from "../../../feature/data/feature.service";
30
+ import { S3Interface } from "../../../s3";
31
31
  import { S3Service } from "../../../s3/data/s3.service";
32
32
  import { UserInterface } from "../../../user";
33
33
  import { useCurrentUserContext } from "../../../user/contexts";
@@ -122,7 +122,7 @@ function CompanyEditorInternal({ company, propagateChanges, onRevalidate }: Comp
122
122
  if (hasRole(getRoleId().Administrator)) {
123
123
  setFeatures(allfeatures);
124
124
  } else {
125
- setFeatures(allfeatures.filter((feature) => feature.isProduction));
125
+ setFeatures(allfeatures.filter((feature) => feature.isCore));
126
126
  }
127
127
  }
128
128
  if (
@@ -26,8 +26,8 @@ import {
26
26
  Link,
27
27
  } from "../../../../shadcnui";
28
28
  import { UserInterface } from "../../../user";
29
- import { UserService } from "../../../user/data/user.service";
30
29
  import { useCurrentUserContext } from "../../../user/contexts";
30
+ import { UserService } from "../../../user/data/user.service";
31
31
  import { CompanyInput } from "../../data";
32
32
  import { CompanyService } from "../../data/company.service";
33
33
 
@@ -154,11 +154,11 @@ export default function CompanyLicense({ onRevalidate, onUpdateToken }: CompanyL
154
154
  <CardHeader>
155
155
  <CardTitle>Company License Required</CardTitle>
156
156
  <CardDescription className={`flex w-full flex-col`}>
157
- <div>You need to activate your license to use Phlow.</div>
157
+ <div>You need to activate your license to use Only35.</div>
158
158
  <div>
159
159
  <span>To obtain your license, please visit</span>
160
- <Link href="https://phlow.com" target="_blank" className={`text-primary`}>
161
- our website (https://phlow.com)
160
+ <Link href="https://only35.com" target="_blank" className={`text-primary`}>
161
+ our website (https://only35.com)
162
162
  </Link>
163
163
  <span>, register for an account and follow the instructions provided.</span>
164
164
  </div>
@@ -10,7 +10,7 @@ import { Action } from "../../../permissions";
10
10
  import { getRoleId } from "../../../roles";
11
11
  import { UserInterface } from "../../user";
12
12
  import { useCurrentUserContext } from "../../user/contexts";
13
- import { CompanyConfigurationEditor, CompanyDeleter, CompanyEditor } from "../components";
13
+ import { CompanyDeleter, CompanyEditor } from "../components";
14
14
  import { CompanyInterface } from "../data";
15
15
 
16
16
  interface CompanyContextType {
@@ -71,7 +71,7 @@ export const CompanyProvider = ({ children, dehydratedCompany }: CompanyProvider
71
71
  hasRole(getRoleId().Administrator) ||
72
72
  hasPermissionToModule({ module: Modules.Company, action: Action.Update })
73
73
  ) {
74
- if (company) functions.push(<CompanyConfigurationEditor key="companyConfigurationEditor" company={company} />);
74
+ // if (company) functions.push(<CompanyConfigurationEditor key="companyConfigurationEditor" company={company} />);
75
75
  functions.push(<CompanyEditor key="companyEditor" company={company} propagateChanges={setCompany} />);
76
76
  }
77
77