@carlonicora/nextjs-jsonapi 1.15.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 (271) 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-ITJLAOXC.mjs → BlockNoteEditor-HFX7Z5BQ.mjs} +5 -5
  4. package/dist/{BlockNoteEditor-FGXYUAWI.js → BlockNoteEditor-MBFDWP7X.js} +15 -15
  5. package/dist/{BlockNoteEditor-FGXYUAWI.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-C6QXZGL7.js → chunk-2AZLCF6D.js} +1617 -158
  10. package/dist/chunk-2AZLCF6D.js.map +1 -0
  11. package/dist/{chunk-WAFOKMKT.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-JGVXZS7M.mjs → chunk-BCQSE3EU.mjs} +1588 -129
  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-PK5DRSUD.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 +521 -18
  44. package/dist/core/index.d.ts +521 -18
  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/index.d.ts +8 -0
  61. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
  62. package/dist/scripts/generate-web-module/templates/index.js +18 -1
  63. package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
  64. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts +7 -0
  65. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.d.ts.map +1 -0
  66. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js +141 -0
  67. package/dist/scripts/generate-web-module/templates/project/bootstrapper.template.js.map +1 -0
  68. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts +7 -0
  69. package/dist/scripts/generate-web-module/templates/project/env.template.d.ts.map +1 -0
  70. package/dist/scripts/generate-web-module/templates/project/env.template.js +110 -0
  71. package/dist/scripts/generate-web-module/templates/project/env.template.js.map +1 -0
  72. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts +7 -0
  73. package/dist/scripts/generate-web-module/templates/project/main-layout.template.d.ts.map +1 -0
  74. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js +101 -0
  75. package/dist/scripts/generate-web-module/templates/project/main-layout.template.js.map +1 -0
  76. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts +7 -0
  77. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.d.ts.map +1 -0
  78. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js +66 -0
  79. package/dist/scripts/generate-web-module/templates/project/middleware-env.template.js.map +1 -0
  80. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts +7 -0
  81. package/dist/scripts/generate-web-module/templates/project/settings-container.template.d.ts.map +1 -0
  82. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js +257 -0
  83. package/dist/scripts/generate-web-module/templates/project/settings-container.template.js.map +1 -0
  84. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts +7 -0
  85. package/dist/scripts/generate-web-module/templates/project/settings-context.template.d.ts.map +1 -0
  86. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js +124 -0
  87. package/dist/scripts/generate-web-module/templates/project/settings-context.template.js.map +1 -0
  88. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts +7 -0
  89. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.d.ts.map +1 -0
  90. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js +78 -0
  91. package/dist/scripts/generate-web-module/templates/project/settings-module-page.template.js.map +1 -0
  92. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts +7 -0
  93. package/dist/scripts/generate-web-module/templates/project/settings-page.template.d.ts.map +1 -0
  94. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js +75 -0
  95. package/dist/scripts/generate-web-module/templates/project/settings-page.template.js.map +1 -0
  96. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +1 -1
  97. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
  98. package/dist/server/index.d.mts +4 -4
  99. package/dist/server/index.d.ts +4 -4
  100. package/dist/server/index.js +12 -12
  101. package/dist/server/index.mjs +2 -2
  102. package/dist/stripe-subscription.interface-C63L6hVg.d.mts +226 -0
  103. package/dist/stripe-subscription.interface-CUvNDvw5.d.ts +226 -0
  104. package/dist/{useSocket-Bua6MwLi.d.mts → useSocket-BpenBR2z.d.mts} +1 -1
  105. package/dist/{useSocket-D5dhUp4m.d.ts → useSocket-D-QYA0Sr.d.ts} +1 -1
  106. package/package.json +9 -1
  107. package/scripts/generate-web-module/generator.ts +83 -0
  108. package/scripts/generate-web-module/templates/index.ts +10 -0
  109. package/scripts/generate-web-module/templates/project/bootstrapper.template.ts +108 -0
  110. package/scripts/generate-web-module/templates/project/env.template.ts +77 -0
  111. package/scripts/generate-web-module/templates/project/main-layout.template.tsx +68 -0
  112. package/scripts/generate-web-module/templates/project/middleware-env.template.ts +33 -0
  113. package/scripts/generate-web-module/templates/project/settings-container.template.tsx +224 -0
  114. package/scripts/generate-web-module/templates/project/settings-context.template.tsx +91 -0
  115. package/scripts/generate-web-module/templates/project/settings-module-page.template.tsx +45 -0
  116. package/scripts/generate-web-module/templates/project/settings-page.template.tsx +42 -0
  117. package/scripts/generate-web-module/types/template-data.interface.ts +1 -1
  118. package/src/client/config.ts +9 -0
  119. package/src/components/index.ts +7 -0
  120. package/src/core/abstracts/AbstractService.ts +104 -0
  121. package/src/core/endpoint/EndpointCreator.ts +7 -4
  122. package/src/core/index.ts +12 -4
  123. package/src/core/interfaces/ApiResponseInterface.ts +1 -0
  124. package/src/core/registry/ModuleRegistry.ts +11 -2
  125. package/src/core/utils/translateResponse.ts +17 -0
  126. package/src/features/billing/components/cards/BillingUsageSummaryCard.tsx +97 -0
  127. package/src/features/billing/components/cards/CustomerInfoCard.tsx +112 -0
  128. package/src/features/billing/components/cards/InvoicesSummaryCard.tsx +114 -0
  129. package/src/features/billing/components/cards/PaymentMethodSummaryCard.tsx +119 -0
  130. package/src/features/billing/components/cards/SubscriptionSummaryCard.tsx +146 -0
  131. package/src/features/billing/components/cards/index.ts +5 -0
  132. package/src/features/billing/components/containers/BillingDashboardContainer.tsx +427 -0
  133. package/src/features/billing/components/containers/index.ts +1 -0
  134. package/src/features/billing/components/index.ts +6 -0
  135. package/src/features/billing/components/modals/BillingDetailModal.tsx +36 -0
  136. package/src/features/billing/components/modals/index.ts +1 -0
  137. package/src/features/billing/components/providers/StripeProvider.tsx +48 -0
  138. package/src/features/billing/components/providers/index.ts +1 -0
  139. package/src/features/billing/components/utils/currency.ts +49 -0
  140. package/src/features/billing/components/utils/date.ts +21 -0
  141. package/src/features/billing/components/utils/index.ts +2 -0
  142. package/src/features/billing/components/widgets/BillingAlertBanner.tsx +63 -0
  143. package/src/features/billing/components/widgets/index.ts +1 -0
  144. package/src/features/billing/data/Billing.ts +17 -0
  145. package/src/features/billing/data/billing.service.ts +58 -0
  146. package/src/features/billing/data/index.ts +5 -0
  147. package/src/features/billing/index.ts +3 -0
  148. package/src/features/billing/modules/billing.module.ts +9 -0
  149. package/src/features/billing/modules/index.ts +1 -0
  150. package/src/features/billing/stripe-customer/components/containers/PaymentMethodsContainer.tsx +79 -0
  151. package/src/features/billing/stripe-customer/components/containers/index.ts +1 -0
  152. package/src/features/billing/stripe-customer/components/details/PaymentMethodCard.tsx +151 -0
  153. package/src/features/billing/stripe-customer/components/details/index.ts +1 -0
  154. package/src/features/billing/stripe-customer/components/forms/PaymentMethodEditor.tsx +186 -0
  155. package/src/features/billing/stripe-customer/components/forms/index.ts +1 -0
  156. package/src/features/billing/stripe-customer/components/index.ts +4 -0
  157. package/src/features/billing/stripe-customer/components/lists/PaymentMethodsList.tsx +19 -0
  158. package/src/features/billing/stripe-customer/components/lists/index.ts +1 -0
  159. package/src/features/billing/stripe-customer/data/index.ts +5 -0
  160. package/src/features/billing/stripe-customer/data/payment-method.interface.ts +27 -0
  161. package/src/features/billing/stripe-customer/data/payment-method.ts +119 -0
  162. package/src/features/billing/stripe-customer/data/stripe-customer.interface.ts +16 -0
  163. package/src/features/billing/stripe-customer/data/stripe-customer.service.ts +128 -0
  164. package/src/features/billing/stripe-customer/data/stripe-customer.ts +71 -0
  165. package/src/features/billing/stripe-customer/index.ts +3 -0
  166. package/src/features/billing/stripe-customer/stripe-customer.module.ts +9 -0
  167. package/src/features/billing/stripe-customer/stripe-payment-method.module.ts +9 -0
  168. package/src/features/billing/stripe-invoice/components/containers/InvoicesContainer.tsx +66 -0
  169. package/src/features/billing/stripe-invoice/components/containers/index.ts +1 -0
  170. package/src/features/billing/stripe-invoice/components/details/InvoiceDetails.tsx +172 -0
  171. package/src/features/billing/stripe-invoice/components/details/index.ts +1 -0
  172. package/src/features/billing/stripe-invoice/components/index.ts +4 -0
  173. package/src/features/billing/stripe-invoice/components/lists/InvoicesList.tsx +84 -0
  174. package/src/features/billing/stripe-invoice/components/lists/index.ts +1 -0
  175. package/src/features/billing/stripe-invoice/components/widgets/InvoiceStatusBadge.tsx +41 -0
  176. package/src/features/billing/stripe-invoice/components/widgets/index.ts +1 -0
  177. package/src/features/billing/stripe-invoice/data/index.ts +3 -0
  178. package/src/features/billing/stripe-invoice/data/stripe-invoice.interface.ts +65 -0
  179. package/src/features/billing/stripe-invoice/data/stripe-invoice.service.ts +64 -0
  180. package/src/features/billing/stripe-invoice/data/stripe-invoice.ts +177 -0
  181. package/src/features/billing/stripe-invoice/index.ts +2 -0
  182. package/src/features/billing/stripe-invoice/stripe-invoice.module.ts +9 -0
  183. package/src/features/billing/stripe-price/components/forms/PriceEditor.tsx +304 -0
  184. package/src/features/billing/stripe-price/components/forms/index.ts +1 -0
  185. package/src/features/billing/stripe-price/components/index.ts +2 -0
  186. package/src/features/billing/stripe-price/components/lists/PricesList.tsx +283 -0
  187. package/src/features/billing/stripe-price/components/lists/index.ts +1 -0
  188. package/src/features/billing/stripe-price/data/index.ts +3 -0
  189. package/src/features/billing/stripe-price/data/stripe-price.interface.ts +48 -0
  190. package/src/features/billing/stripe-price/data/stripe-price.service.ts +123 -0
  191. package/src/features/billing/stripe-price/data/stripe-price.ts +156 -0
  192. package/src/features/billing/stripe-price/index.ts +2 -0
  193. package/src/features/billing/stripe-price/stripe-price.module.ts +9 -0
  194. package/src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx +86 -0
  195. package/src/features/billing/stripe-product/components/containers/index.ts +1 -0
  196. package/src/features/billing/stripe-product/components/forms/ProductEditor.tsx +100 -0
  197. package/src/features/billing/stripe-product/components/forms/index.ts +1 -0
  198. package/src/features/billing/stripe-product/components/index.ts +3 -0
  199. package/src/features/billing/stripe-product/components/lists/ProductsList.tsx +206 -0
  200. package/src/features/billing/stripe-product/components/lists/index.ts +1 -0
  201. package/src/features/billing/stripe-product/data/index.ts +3 -0
  202. package/src/features/billing/stripe-product/data/stripe-product.interface.ts +18 -0
  203. package/src/features/billing/stripe-product/data/stripe-product.service.ts +112 -0
  204. package/src/features/billing/stripe-product/data/stripe-product.ts +74 -0
  205. package/src/features/billing/stripe-product/index.ts +2 -0
  206. package/src/features/billing/stripe-product/stripe-product.module.ts +9 -0
  207. package/src/features/billing/stripe-subscription/components/containers/SubscriptionsContainer.tsx +304 -0
  208. package/src/features/billing/stripe-subscription/components/containers/index.ts +1 -0
  209. package/src/features/billing/stripe-subscription/components/details/SubscriptionDetails.tsx +223 -0
  210. package/src/features/billing/stripe-subscription/components/details/index.ts +1 -0
  211. package/src/features/billing/stripe-subscription/components/forms/CancelSubscriptionDialog.tsx +116 -0
  212. package/src/features/billing/stripe-subscription/components/forms/SubscriptionEditor.tsx +331 -0
  213. package/src/features/billing/stripe-subscription/components/forms/index.ts +2 -0
  214. package/src/features/billing/stripe-subscription/components/index.ts +5 -0
  215. package/src/features/billing/stripe-subscription/components/lists/SubscriptionsList.tsx +104 -0
  216. package/src/features/billing/stripe-subscription/components/lists/index.ts +1 -0
  217. package/src/features/billing/stripe-subscription/components/widgets/PricingCard.tsx +95 -0
  218. package/src/features/billing/stripe-subscription/components/widgets/PricingCardsGrid.tsx +110 -0
  219. package/src/features/billing/stripe-subscription/components/widgets/ProrationPreview.tsx +41 -0
  220. package/src/features/billing/stripe-subscription/components/widgets/SubscriptionStatusBadge.tsx +60 -0
  221. package/src/features/billing/stripe-subscription/components/widgets/index.ts +4 -0
  222. package/src/features/billing/stripe-subscription/data/index.ts +3 -0
  223. package/src/features/billing/stripe-subscription/data/stripe-subscription.interface.ts +66 -0
  224. package/src/features/billing/stripe-subscription/data/stripe-subscription.service.ts +193 -0
  225. package/src/features/billing/stripe-subscription/data/stripe-subscription.ts +135 -0
  226. package/src/features/billing/stripe-subscription/hooks/index.ts +1 -0
  227. package/src/features/billing/stripe-subscription/hooks/useConfirmSubscriptionPayment.ts +111 -0
  228. package/src/features/billing/stripe-subscription/index.ts +5 -0
  229. package/src/features/billing/stripe-subscription/stripe-subscription.module.ts +9 -0
  230. package/src/features/billing/stripe-usage/components/containers/UsageContainer.tsx +109 -0
  231. package/src/features/billing/stripe-usage/components/containers/index.ts +1 -0
  232. package/src/features/billing/stripe-usage/components/details/UsageSummaryCard.tsx +90 -0
  233. package/src/features/billing/stripe-usage/components/details/index.ts +1 -0
  234. package/src/features/billing/stripe-usage/components/index.ts +4 -0
  235. package/src/features/billing/stripe-usage/components/lists/UsageHistoryTable.tsx +72 -0
  236. package/src/features/billing/stripe-usage/components/lists/index.ts +1 -0
  237. package/src/features/billing/stripe-usage/components/widgets/UsageSummaryCards.tsx +19 -0
  238. package/src/features/billing/stripe-usage/components/widgets/index.ts +1 -0
  239. package/src/features/billing/stripe-usage/data/index.ts +3 -0
  240. package/src/features/billing/stripe-usage/data/stripe-usage.interface.ts +55 -0
  241. package/src/features/billing/stripe-usage/data/stripe-usage.service.ts +129 -0
  242. package/src/features/billing/stripe-usage/data/stripe-usage.ts +70 -0
  243. package/src/features/billing/stripe-usage/index.ts +2 -0
  244. package/src/features/billing/stripe-usage/stripe-usage.module.ts +9 -0
  245. package/src/features/company/components/forms/CompanyEditor.tsx +2 -2
  246. package/src/features/company/contexts/CompanyContext.tsx +2 -2
  247. package/src/features/feature/components/forms/FormFeatures.tsx +13 -106
  248. package/src/features/feature/data/feature.interface.ts +1 -1
  249. package/src/features/feature/data/feature.ts +4 -4
  250. package/src/features/index.ts +7 -0
  251. package/src/features/module/data/module.interface.ts +0 -1
  252. package/src/features/module/data/module.ts +0 -6
  253. package/src/features/user/components/lists/ContributorsList.tsx +2 -2
  254. package/src/features/user/components/widgets/UserAvatar.tsx +1 -1
  255. package/src/index.ts +1 -1
  256. package/src/shadcnui/custom/link.tsx +16 -6
  257. package/src/utils/blocknote-diff.util.ts +2 -1
  258. package/src/utils/blocknote-word-diff-renderer.util.ts +8 -7
  259. package/dist/AuthComponent-hxOPs9o8.d.mts +0 -11
  260. package/dist/AuthComponent-hxOPs9o8.d.ts +0 -11
  261. package/dist/JsonApiRequest-FXZCYIER.js +0 -24
  262. package/dist/chunk-6YD42BP6.js.map +0 -1
  263. package/dist/chunk-C6QXZGL7.js.map +0 -1
  264. package/dist/chunk-FPZPD4JI.js.map +0 -1
  265. package/dist/chunk-JGVXZS7M.mjs.map +0 -1
  266. package/dist/chunk-PK5DRSUD.js.map +0 -1
  267. package/dist/chunk-SJIVGCNM.mjs.map +0 -1
  268. package/dist/chunk-TGBXBUWM.mjs.map +0 -1
  269. package/dist/chunk-WAFOKMKT.mjs.map +0 -1
  270. /package/dist/{BlockNoteEditor-ITJLAOXC.mjs.map → BlockNoteEditor-HFX7Z5BQ.mjs.map} +0 -0
  271. /package/dist/{JsonApiRequest-HFWXMKMA.mjs.map → JsonApiRequest-6IPS3DZJ.mjs.map} +0 -0
@@ -0,0 +1,206 @@
1
+ "use client";
2
+
3
+ import { Archive, ChevronDown, ChevronUp, Edit, Package, RefreshCw } from "lucide-react";
4
+ import { useState } from "react";
5
+ import {
6
+ AlertDialog,
7
+ AlertDialogAction,
8
+ AlertDialogCancel,
9
+ AlertDialogContent,
10
+ AlertDialogDescription,
11
+ AlertDialogFooter,
12
+ AlertDialogHeader,
13
+ AlertDialogTitle,
14
+ Button,
15
+ } from "../../../../../shadcnui";
16
+ import { PricesList } from "../../../stripe-price/components/lists/PricesList";
17
+ import { StripeProductInterface } from "../../data/stripe-product.interface";
18
+ import { StripeProductService } from "../../data/stripe-product.service";
19
+ import { ProductEditor } from "../forms/ProductEditor";
20
+
21
+ type ProductsListProps = {
22
+ products: StripeProductInterface[];
23
+ onProductsChange: () => void;
24
+ };
25
+
26
+ export function ProductsList({ products, onProductsChange }: ProductsListProps) {
27
+ const [expandedProductId, setExpandedProductId] = useState<string | null>(null);
28
+ const [editingProduct, setEditingProduct] = useState<StripeProductInterface | null>(null);
29
+ const [archivingProductId, setArchivingProductId] = useState<string | null>(null);
30
+ const [reactivatingProductId, setReactivatingProductId] = useState<string | null>(null);
31
+ const [productToArchive, setProductToArchive] = useState<StripeProductInterface | null>(null);
32
+ const [productToReactivate, setProductToReactivate] = useState<StripeProductInterface | null>(null);
33
+
34
+ const handleArchive = async () => {
35
+ if (!productToArchive) {
36
+ return;
37
+ }
38
+
39
+ setArchivingProductId(productToArchive.id);
40
+ try {
41
+ const archivedProduct = await StripeProductService.archiveProduct({ id: productToArchive.id });
42
+ setProductToArchive(null); // Close dialog on success
43
+ onProductsChange();
44
+ } catch (error) {
45
+ console.error("[ProductsList] Failed to archive product:", error);
46
+ // Keep dialog open on error so user can retry or cancel
47
+ } finally {
48
+ setArchivingProductId(null);
49
+ }
50
+ };
51
+
52
+ const handleReactivate = async () => {
53
+ if (!productToReactivate) {
54
+ return;
55
+ }
56
+
57
+ setReactivatingProductId(productToReactivate.id);
58
+ try {
59
+ const reactivatedProduct = await StripeProductService.reactivateProduct({ id: productToReactivate.id });
60
+ setProductToReactivate(null); // Close dialog on success
61
+ onProductsChange();
62
+ } catch (error) {
63
+ // Keep dialog open on error so user can retry or cancel
64
+ } finally {
65
+ setReactivatingProductId(null);
66
+ }
67
+ };
68
+
69
+ const toggleExpand = (productId: string) => {
70
+ setExpandedProductId(expandedProductId === productId ? null : productId);
71
+ };
72
+
73
+ return (
74
+ <div className="flex flex-col gap-y-4">
75
+ {products.map((product) => {
76
+ const isExpanded = expandedProductId === product.id;
77
+ const isArchiving = archivingProductId === product.id;
78
+ const isReactivating = reactivatingProductId === product.id;
79
+
80
+ return (
81
+ <div key={product.id} className="border rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow">
82
+ {/* Product Card Header */}
83
+ <div className="flex items-center justify-between p-6">
84
+ <div className="flex items-center gap-x-4 flex-1">
85
+ <Package className="h-6 w-6 text-primary" />
86
+ <div className="flex-1">
87
+ <div className="flex items-center gap-x-3">
88
+ <h3 className="text-lg font-semibold">{product.name}</h3>
89
+ {product.active ? (
90
+ <span className="bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full font-medium">
91
+ Active
92
+ </span>
93
+ ) : (
94
+ <span className="bg-gray-100 text-gray-800 text-xs px-2 py-1 rounded-full font-medium">
95
+ Inactive
96
+ </span>
97
+ )}
98
+ </div>
99
+ {product.description && <p className="text-muted-foreground text-sm mt-1">{product.description}</p>}
100
+ </div>
101
+ </div>
102
+
103
+ {/* Action Buttons */}
104
+ <div className="flex items-center gap-x-2">
105
+ <Button variant="outline" size="sm" onClick={() => setEditingProduct(product)}>
106
+ <Edit className="h-4 w-4 mr-1" />
107
+ Edit
108
+ </Button>
109
+ {product.active ? (
110
+ <Button
111
+ variant="outline"
112
+ size="sm"
113
+ onClick={() => setProductToArchive(product)}
114
+ disabled={isArchiving}
115
+ >
116
+ <Archive className="h-4 w-4 mr-1" />
117
+ {isArchiving ? "Archiving..." : "Archive"}
118
+ </Button>
119
+ ) : (
120
+ <Button
121
+ variant="outline"
122
+ size="sm"
123
+ onClick={() => setProductToReactivate(product)}
124
+ disabled={isReactivating}
125
+ >
126
+ <RefreshCw className="h-4 w-4 mr-1" />
127
+ {isReactivating ? "Reactivating..." : "Reactivate"}
128
+ </Button>
129
+ )}
130
+ <Button variant="ghost" size="sm" onClick={() => toggleExpand(product.id)}>
131
+ {isExpanded ? <ChevronUp className="h-5 w-5" /> : <ChevronDown className="h-5 w-5" />}
132
+ </Button>
133
+ </div>
134
+ </div>
135
+
136
+ {/* Expandable Prices Section */}
137
+ {isExpanded && (
138
+ <div className="border-t bg-muted/30 p-6">
139
+ <PricesList productId={product.id} onPricesChange={onProductsChange} />
140
+ </div>
141
+ )}
142
+ </div>
143
+ );
144
+ })}
145
+
146
+ {/* Edit Product Modal */}
147
+ {editingProduct && (
148
+ <ProductEditor
149
+ product={editingProduct}
150
+ open={!!editingProduct}
151
+ onOpenChange={(open) => !open && setEditingProduct(null)}
152
+ onSuccess={() => {
153
+ onProductsChange();
154
+ setEditingProduct(null);
155
+ }}
156
+ />
157
+ )}
158
+
159
+ {/* Archive Product Confirmation Dialog */}
160
+ <AlertDialog open={!!productToArchive} onOpenChange={(open) => !open && setProductToArchive(null)}>
161
+ <AlertDialogContent>
162
+ <AlertDialogHeader>
163
+ <AlertDialogTitle>Archive Product</AlertDialogTitle>
164
+ <AlertDialogDescription>
165
+ Are you sure you want to archive &quot;{productToArchive?.name}&quot;? This will deactivate it and it will
166
+ no longer be available for new subscriptions.
167
+ </AlertDialogDescription>
168
+ </AlertDialogHeader>
169
+ <AlertDialogFooter>
170
+ <AlertDialogCancel disabled={!!archivingProductId}>Cancel</AlertDialogCancel>
171
+ <AlertDialogAction
172
+ onClick={handleArchive}
173
+ disabled={!!archivingProductId}
174
+ className="bg-red-600 hover:bg-red-700"
175
+ >
176
+ {archivingProductId ? "Archiving..." : "Archive"}
177
+ </AlertDialogAction>
178
+ </AlertDialogFooter>
179
+ </AlertDialogContent>
180
+ </AlertDialog>
181
+
182
+ {/* Reactivate Product Confirmation Dialog */}
183
+ <AlertDialog open={!!productToReactivate} onOpenChange={(open) => !open && setProductToReactivate(null)}>
184
+ <AlertDialogContent>
185
+ <AlertDialogHeader>
186
+ <AlertDialogTitle>Reactivate Product</AlertDialogTitle>
187
+ <AlertDialogDescription>
188
+ Are you sure you want to reactivate &quot;{productToReactivate?.name}&quot;? This will make it available
189
+ for new subscriptions again.
190
+ </AlertDialogDescription>
191
+ </AlertDialogHeader>
192
+ <AlertDialogFooter>
193
+ <AlertDialogCancel disabled={!!reactivatingProductId}>Cancel</AlertDialogCancel>
194
+ <AlertDialogAction
195
+ onClick={handleReactivate}
196
+ disabled={!!reactivatingProductId}
197
+ className="bg-green-600 hover:bg-green-700"
198
+ >
199
+ {reactivatingProductId ? "Reactivating..." : "Reactivate"}
200
+ </AlertDialogAction>
201
+ </AlertDialogFooter>
202
+ </AlertDialogContent>
203
+ </AlertDialog>
204
+ </div>
205
+ );
206
+ }
@@ -0,0 +1 @@
1
+ export * from "./ProductsList";
@@ -0,0 +1,3 @@
1
+ export * from "./stripe-product";
2
+ export * from "./stripe-product.interface";
3
+ export * from "./stripe-product.service";
@@ -0,0 +1,18 @@
1
+ import { ApiDataInterface, StripePriceInterface } from "../../../../core";
2
+
3
+ export interface StripeProductInterface extends ApiDataInterface {
4
+ get stripeProductId(): string;
5
+ get name(): string;
6
+ get description(): string | undefined;
7
+ get active(): boolean;
8
+ get metadata(): Record<string, any> | undefined;
9
+ get stripePrices(): StripePriceInterface[];
10
+ }
11
+
12
+ export type StripeProductInput = {
13
+ id: string;
14
+ name?: string;
15
+ description?: string;
16
+ active?: boolean;
17
+ metadata?: Record<string, any>;
18
+ };
@@ -0,0 +1,112 @@
1
+ import { AbstractService, EndpointCreator, HttpMethod, Modules, NextRef, PreviousRef } from "../../../../core";
2
+ import { StripeProductInput, StripeProductInterface } from "./stripe-product.interface";
3
+
4
+ export class StripeProductService extends AbstractService {
5
+ /**
6
+ * List all products (admin)
7
+ */
8
+ static async listProducts(params?: {
9
+ active?: boolean;
10
+ next?: NextRef;
11
+ prev?: PreviousRef;
12
+ }): Promise<StripeProductInterface[]> {
13
+ const endpoint = new EndpointCreator({
14
+ endpoint: Modules.StripeProduct,
15
+ });
16
+
17
+ if (params?.active !== undefined) {
18
+ endpoint.addAdditionalParam("active", params.active.toString());
19
+ }
20
+
21
+ return this.callApi({
22
+ type: Modules.StripeProduct,
23
+ method: HttpMethod.GET,
24
+ endpoint: endpoint.generate(),
25
+ next: params?.next,
26
+ previous: params?.prev,
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Get a specific product by ID (admin)
32
+ */
33
+ static async getProduct(params: { id: string }): Promise<StripeProductInterface> {
34
+ const endpoint = new EndpointCreator({
35
+ endpoint: Modules.StripeProduct,
36
+ id: params.id,
37
+ });
38
+
39
+ return this.callApi<StripeProductInterface>({
40
+ type: Modules.StripeProduct,
41
+ method: HttpMethod.GET,
42
+ endpoint: endpoint.generate(),
43
+ });
44
+ }
45
+
46
+ /**
47
+ * Create a new product (admin)
48
+ */
49
+ static async createProduct(params: StripeProductInput): Promise<StripeProductInterface> {
50
+ const endpoint = new EndpointCreator({
51
+ endpoint: Modules.StripeProduct,
52
+ });
53
+
54
+ return this.callApi<StripeProductInterface>({
55
+ type: Modules.StripeProduct,
56
+ method: HttpMethod.POST,
57
+ endpoint: endpoint.generate(),
58
+ input: params,
59
+ });
60
+ }
61
+
62
+ /**
63
+ * Update an existing product (admin)
64
+ */
65
+ static async updateProduct(params: StripeProductInput): Promise<StripeProductInterface> {
66
+ const endpoint = new EndpointCreator({
67
+ endpoint: Modules.StripeProduct,
68
+ id: params.id,
69
+ });
70
+
71
+ return this.callApi<StripeProductInterface>({
72
+ type: Modules.StripeProduct,
73
+ method: HttpMethod.PUT,
74
+ endpoint: endpoint.generate(),
75
+ input: params,
76
+ });
77
+ }
78
+
79
+ /**
80
+ * Archive a product (admin)
81
+ */
82
+ static async archiveProduct(params: { id: string }): Promise<StripeProductInterface> {
83
+ const endpoint = new EndpointCreator({
84
+ endpoint: Modules.StripeProduct,
85
+ id: params.id,
86
+ childEndpoint: "archive",
87
+ });
88
+
89
+ return this.callApi<StripeProductInterface>({
90
+ type: Modules.StripeProduct,
91
+ method: HttpMethod.POST,
92
+ endpoint: endpoint.generate(),
93
+ });
94
+ }
95
+
96
+ /**
97
+ * Reactivate a product (admin) - sets active to true
98
+ */
99
+ static async reactivateProduct(params: { id: string }): Promise<StripeProductInterface> {
100
+ const endpoint = new EndpointCreator({
101
+ endpoint: Modules.StripeProduct,
102
+ id: params.id,
103
+ childEndpoint: "archive",
104
+ });
105
+
106
+ return this.callApi<StripeProductInterface>({
107
+ type: Modules.StripeProduct,
108
+ method: HttpMethod.DELETE,
109
+ endpoint: endpoint.generate(),
110
+ });
111
+ }
112
+ }
@@ -0,0 +1,74 @@
1
+ import { AbstractApiData, JsonApiHydratedDataInterface, Modules, StripePriceInterface } from "../../../../core";
2
+ import { StripeProductInput, StripeProductInterface } from "./stripe-product.interface";
3
+
4
+ export class StripeProduct extends AbstractApiData implements StripeProductInterface {
5
+ private _stripeProductId?: string;
6
+ private _name?: string;
7
+ private _description?: string;
8
+ private _active: boolean = true;
9
+ private _metadata?: Record<string, any>;
10
+
11
+ private _stripePrices: StripePriceInterface[] = [];
12
+
13
+ get stripeProductId(): string {
14
+ if (!this._stripeProductId) throw new Error("stripeProductId is not defined");
15
+ return this._stripeProductId;
16
+ }
17
+
18
+ get name(): string {
19
+ if (!this._name) throw new Error("name is not defined");
20
+ return this._name;
21
+ }
22
+
23
+ get description(): string | undefined {
24
+ return this._description;
25
+ }
26
+
27
+ get active(): boolean {
28
+ return this._active;
29
+ }
30
+
31
+ get metadata(): Record<string, any> | undefined {
32
+ return this._metadata;
33
+ }
34
+
35
+ get stripePrices(): StripePriceInterface[] {
36
+ return this._stripePrices ?? [];
37
+ }
38
+
39
+ rehydrate(data: JsonApiHydratedDataInterface): this {
40
+ super.rehydrate(data);
41
+
42
+ this._stripeProductId = data.jsonApi.attributes.stripeProductId;
43
+ this._name = data.jsonApi.attributes.name;
44
+ this._description = data.jsonApi.attributes.description;
45
+ this._active = data.jsonApi.attributes.active ?? true;
46
+
47
+ this._metadata = data.jsonApi.attributes.metadata
48
+ ? typeof data.jsonApi.attributes.metadata === "string"
49
+ ? JSON.parse(data.jsonApi.attributes.metadata)
50
+ : data.jsonApi.attributes.metadata
51
+ : undefined;
52
+
53
+ this._stripePrices = this._readIncluded(data, "stripePrices", Modules.StripePrice) as StripePriceInterface[];
54
+
55
+ return this;
56
+ }
57
+
58
+ createJsonApi(data: StripeProductInput): any {
59
+ const response: any = {
60
+ data: {
61
+ type: Modules.StripeProduct.name,
62
+ id: data.id,
63
+ attributes: {},
64
+ },
65
+ };
66
+
67
+ if (data.name) response.data.attributes.name = data.name;
68
+ if (data.description !== undefined) response.data.attributes.description = data.description;
69
+ if (data.active !== undefined) response.data.attributes.active = data.active;
70
+ if (data.metadata) response.data.attributes.metadata = data.metadata;
71
+
72
+ return response;
73
+ }
74
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./data";
2
+ export * from "./stripe-product.module";
@@ -0,0 +1,9 @@
1
+ import { ModuleFactory } from "../../../permissions";
2
+ import { StripeProduct } from "./data";
3
+
4
+ export const StripeProductModule = (factory: ModuleFactory) =>
5
+ factory({
6
+ name: "stripe-products",
7
+ model: StripeProduct,
8
+ moduleId: "f8c4a1e9-3b2d-4f7a-9e5c-1d8a6b3c9f2e",
9
+ });