@carlonicora/nextjs-jsonapi 2.3.0 → 2.5.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 (124) hide show
  1. package/dist/{BlockNoteEditor-PNAVMGHB.js → BlockNoteEditor-TIMGYKAA.js} +19 -19
  2. package/dist/{BlockNoteEditor-PNAVMGHB.js.map → BlockNoteEditor-TIMGYKAA.js.map} +1 -1
  3. package/dist/{BlockNoteEditor-3PS3HYVI.mjs → BlockNoteEditor-YFJMXJEU.mjs} +4 -4
  4. package/dist/billing/index.d.mts +40 -1
  5. package/dist/billing/index.d.ts +40 -1
  6. package/dist/billing/index.js +519 -462
  7. package/dist/billing/index.js.map +1 -1
  8. package/dist/billing/index.mjs +298 -241
  9. package/dist/billing/index.mjs.map +1 -1
  10. package/dist/{chunk-QYUYQO2M.js → chunk-7HKJNUW7.js} +1144 -953
  11. package/dist/chunk-7HKJNUW7.js.map +1 -0
  12. package/dist/{chunk-MN2BUSEU.mjs → chunk-DJWNNV52.mjs} +2 -2
  13. package/dist/{chunk-EQEW64CH.mjs → chunk-FS4RVV3K.mjs} +242 -1
  14. package/dist/chunk-FS4RVV3K.mjs.map +1 -0
  15. package/dist/{chunk-FSMXD3N7.mjs → chunk-G4YS52SO.mjs} +2547 -2356
  16. package/dist/chunk-G4YS52SO.mjs.map +1 -0
  17. package/dist/{chunk-OHJQYVSI.js → chunk-OTEDZ6YW.js} +7 -7
  18. package/dist/{chunk-OHJQYVSI.js.map → chunk-OTEDZ6YW.js.map} +1 -1
  19. package/dist/{chunk-X5TPKMBS.js → chunk-RTOC53EZ.js} +247 -6
  20. package/dist/chunk-RTOC53EZ.js.map +1 -0
  21. package/dist/client/index.d.mts +1 -1
  22. package/dist/client/index.d.ts +1 -1
  23. package/dist/client/index.js +4 -4
  24. package/dist/client/index.mjs +3 -3
  25. package/dist/components/index.d.mts +137 -4
  26. package/dist/components/index.d.ts +137 -4
  27. package/dist/components/index.js +16 -4
  28. package/dist/components/index.js.map +1 -1
  29. package/dist/components/index.mjs +15 -3
  30. package/dist/{tokenusage-admin.module-5wJ_tZTj.d.ts → config-BIjrg5wd.d.ts} +39 -1
  31. package/dist/{tokenusage-admin.module-DQVT4O4j.d.mts → config-BRUjtCd1.d.mts} +39 -1
  32. package/dist/{content.fields-xH3TGvVk.d.mts → content.fields-1AlHDtDb.d.mts} +1 -0
  33. package/dist/{content.fields-xH3TGvVk.d.ts → content.fields-1AlHDtDb.d.ts} +1 -0
  34. package/dist/contexts/index.d.mts +22 -1
  35. package/dist/contexts/index.d.ts +22 -1
  36. package/dist/contexts/index.js +8 -4
  37. package/dist/contexts/index.js.map +1 -1
  38. package/dist/contexts/index.mjs +7 -3
  39. package/dist/core/index.d.mts +6 -3
  40. package/dist/core/index.d.ts +6 -3
  41. package/dist/core/index.js +8 -2
  42. package/dist/core/index.js.map +1 -1
  43. package/dist/core/index.mjs +7 -1
  44. package/dist/features/help/index.js +37 -37
  45. package/dist/features/help/index.mjs +3 -3
  46. package/dist/features/tokenusage/index.d.mts +413 -14
  47. package/dist/features/tokenusage/index.d.ts +413 -14
  48. package/dist/features/tokenusage/index.js +481 -120
  49. package/dist/features/tokenusage/index.js.map +1 -1
  50. package/dist/features/tokenusage/index.mjs +431 -70
  51. package/dist/features/tokenusage/index.mjs.map +1 -1
  52. package/dist/index.d.mts +3 -3
  53. package/dist/index.d.ts +3 -3
  54. package/dist/index.js +9 -3
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.mjs +8 -2
  57. package/dist/server/index.js +3 -3
  58. package/dist/server/index.mjs +1 -1
  59. package/package.json +1 -1
  60. package/src/billing/index.ts +1 -0
  61. package/src/components/index.ts +1 -0
  62. package/src/contexts/index.ts +1 -0
  63. package/src/core/index.ts +10 -0
  64. package/src/core/registry/ModuleRegistry.ts +4 -0
  65. package/src/features/administration/components/AdminIndexContainer.tsx +150 -0
  66. package/src/features/administration/components/__tests__/AdminIndexContainer.spec.tsx +96 -0
  67. package/src/features/administration/components/index.ts +1 -0
  68. package/src/features/administration/contexts/AdministrationContext.tsx +47 -0
  69. package/src/features/administration/contexts/index.ts +1 -0
  70. package/src/features/administration/data/admin-section.types.ts +30 -0
  71. package/src/features/administration/i18n-keys.ts +26 -0
  72. package/src/features/administration/index.ts +3 -0
  73. package/src/features/billing/contexts/BillingContext.tsx +95 -0
  74. package/src/features/billing/contexts/index.ts +1 -0
  75. package/src/features/billing/index.ts +1 -0
  76. package/src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx +39 -27
  77. package/src/features/billing/stripe-product/components/containers/ProductsAdminPageContainer.tsx +27 -0
  78. package/src/features/billing/stripe-product/components/containers/index.ts +1 -0
  79. package/src/features/company/components/containers/CompaniesListContainer.tsx +25 -0
  80. package/src/features/company/components/containers/index.ts +1 -0
  81. package/src/features/company/components/lists/CompaniesList.tsx +12 -1
  82. package/src/features/company/contexts/CompanyContext.tsx +13 -1
  83. package/src/features/tokenusage/components/TokenUsageAdminContainer.tsx +20 -4
  84. package/src/features/tokenusage/components/TokenUsageAdminTiles.tsx +31 -18
  85. package/src/features/tokenusage/components/TokenUsageBreakdownTable.tsx +13 -13
  86. package/src/features/tokenusage/components/TokenUsageRankedBar.tsx +24 -7
  87. package/src/features/tokenusage/components/TokenUsageReportContainer.tsx +102 -0
  88. package/src/features/tokenusage/components/TokenUsageReportFilterBar.tsx +34 -0
  89. package/src/features/tokenusage/components/TokenUsageReportTiles.tsx +161 -0
  90. package/src/features/tokenusage/components/TokenUsageTimelineChart.tsx +15 -13
  91. package/src/features/tokenusage/components/__tests__/TokenUsageAdminTiles.spec.tsx +4 -2
  92. package/src/features/tokenusage/components/__tests__/TokenUsageRankedBar.spec.tsx +3 -1
  93. package/src/features/tokenusage/contexts/TokenUsageAdminContext.tsx +6 -3
  94. package/src/features/tokenusage/contexts/TokenUsageReportContext.tsx +199 -0
  95. package/src/features/tokenusage/data/TokenUsageReportService.ts +65 -0
  96. package/src/features/tokenusage/data/index.ts +9 -0
  97. package/src/features/tokenusage/data/tokenusage-report-breakdown.interface.ts +12 -0
  98. package/src/features/tokenusage/data/tokenusage-report-breakdown.ts +94 -0
  99. package/src/features/tokenusage/data/tokenusage-report-summary.interface.ts +12 -0
  100. package/src/features/tokenusage/data/tokenusage-report-summary.ts +87 -0
  101. package/src/features/tokenusage/data/tokenusage-report-timeline.interface.ts +13 -0
  102. package/src/features/tokenusage/data/tokenusage-report-timeline.ts +94 -0
  103. package/src/features/tokenusage/data/tokenusage-report.types.ts +51 -0
  104. package/src/features/tokenusage/i18n-keys.ts +28 -0
  105. package/src/features/tokenusage/index.ts +18 -0
  106. package/src/features/tokenusage/lib/config.ts +22 -0
  107. package/src/features/tokenusage/lib/formatters.ts +100 -0
  108. package/src/features/tokenusage/lib/metrics.ts +8 -26
  109. package/src/features/tokenusage/lib/palette.ts +41 -14
  110. package/src/features/tokenusage/tokenusage-admin.module.ts +4 -0
  111. package/src/features/tokenusage/tokenusage.modules.ts +40 -0
  112. package/src/features/user/components/containers/PlatformUsersContainer.tsx +23 -0
  113. package/src/features/user/components/containers/index.ts +1 -0
  114. package/src/features/user/components/lists/PlatformUsersList.tsx +45 -0
  115. package/src/features/user/components/lists/index.ts +1 -0
  116. package/src/features/user/data/user.fields.ts +1 -0
  117. package/src/features/user/hooks/useUserTableStructure.tsx +17 -0
  118. package/src/shadcnui/ui/chart.tsx +30 -3
  119. package/dist/chunk-EQEW64CH.mjs.map +0 -1
  120. package/dist/chunk-FSMXD3N7.mjs.map +0 -1
  121. package/dist/chunk-QYUYQO2M.js.map +0 -1
  122. package/dist/chunk-X5TPKMBS.js.map +0 -1
  123. /package/dist/{BlockNoteEditor-3PS3HYVI.mjs.map → BlockNoteEditor-YFJMXJEU.mjs.map} +0 -0
  124. /package/dist/{chunk-MN2BUSEU.mjs.map → chunk-DJWNNV52.mjs.map} +0 -0
@@ -36,7 +36,9 @@ import {
36
36
  FormTextarea,
37
37
  Input,
38
38
  Label,
39
+ RoundPageContainer,
39
40
  SectionHeader,
41
+ SharedProvider,
40
42
  Skeleton,
41
43
  Table,
42
44
  TableBody,
@@ -48,13 +50,14 @@ import {
48
50
  TabsList,
49
51
  TabsTrigger,
50
52
  useCurrentUserContext
51
- } from "../chunk-FSMXD3N7.mjs";
53
+ } from "../chunk-G4YS52SO.mjs";
52
54
  import {
53
55
  getRoleId,
54
56
  getStripePublishableKey
55
- } from "../chunk-MN2BUSEU.mjs";
57
+ } from "../chunk-DJWNNV52.mjs";
56
58
  import {
57
59
  FeatureService,
60
+ Modules,
58
61
  StripeCustomerService,
59
62
  StripeInvoiceService,
60
63
  StripePriceService,
@@ -63,7 +66,7 @@ import {
63
66
  StripeSubscriptionService,
64
67
  StripeUsageService,
65
68
  cn
66
- } from "../chunk-EQEW64CH.mjs";
69
+ } from "../chunk-FS4RVV3K.mjs";
67
70
  import "../chunk-AUXK7QSA.mjs";
68
71
  import "../chunk-C7C7VY4F.mjs";
69
72
  import "../chunk-E5YA5Z5X.mjs";
@@ -3100,17 +3103,135 @@ function isStripeConfigured() {
3100
3103
  }
3101
3104
  __name(isStripeConfigured, "isStripeConfigured");
3102
3105
 
3103
- // src/features/billing/stripe-price/components/forms/PriceEditor.tsx
3106
+ // src/features/billing/contexts/BillingContext.tsx
3107
+ import { useTranslations } from "next-intl";
3108
+ import { createContext, useCallback as useCallback5, useContext, useState as useState16 } from "react";
3109
+
3110
+ // src/features/billing/stripe-product/components/forms/ProductEditor.tsx
3104
3111
  import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
3105
- import { AlertCircle as AlertCircle3, PlusIcon, XIcon } from "lucide-react";
3106
- import { useEffect as useEffect10, useState as useState15 } from "react";
3112
+ import { useState as useState15 } from "react";
3107
3113
  import { useForm as useForm2 } from "react-hook-form";
3108
3114
  import { v4 as v42 } from "uuid";
3109
3115
  import { z as z2 } from "zod";
3110
3116
  import { jsx as jsx40, jsxs as jsxs35 } from "react/jsx-runtime";
3111
- function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3117
+ function ProductEditor({ product, open, onOpenChange, onSuccess }) {
3112
3118
  const [isSubmitting, setIsSubmitting] = useState15(false);
3113
- const [allFeatures, setAllFeatures] = useState15([]);
3119
+ const formSchema2 = z2.object({
3120
+ name: z2.string().min(1, { message: "Product name is required" }),
3121
+ description: z2.string().min(1, { message: "Description is required" }),
3122
+ active: z2.boolean()
3123
+ });
3124
+ const form = useForm2({
3125
+ resolver: zodResolver2(formSchema2),
3126
+ defaultValues: {
3127
+ name: product?.name || "",
3128
+ description: product?.description || "",
3129
+ active: product?.active ?? true
3130
+ }
3131
+ });
3132
+ const onSubmit = /* @__PURE__ */ __name(async (values) => {
3133
+ setIsSubmitting(true);
3134
+ try {
3135
+ if (product) {
3136
+ await StripeProductService.updateProduct({
3137
+ id: product.id,
3138
+ name: values.name,
3139
+ description: values.description,
3140
+ active: values.active
3141
+ });
3142
+ } else {
3143
+ await StripeProductService.createProduct({
3144
+ id: v42(),
3145
+ name: values.name,
3146
+ description: values.description,
3147
+ active: values.active
3148
+ });
3149
+ }
3150
+ onSuccess();
3151
+ onOpenChange(false);
3152
+ } catch (error) {
3153
+ console.error("[ProductEditor] Failed to save product:", error);
3154
+ } finally {
3155
+ setIsSubmitting(false);
3156
+ }
3157
+ }, "onSubmit");
3158
+ return /* @__PURE__ */ jsx40(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs35(DialogContent, { className: "max-w-2xl", children: [
3159
+ /* @__PURE__ */ jsxs35(DialogHeader, { children: [
3160
+ /* @__PURE__ */ jsx40(DialogTitle, { children: product ? "Edit Product" : "Create Product" }),
3161
+ /* @__PURE__ */ jsx40(DialogDescription, { children: product ? `Update the details for ${product.name}` : "Create a new product to offer to your customers" })
3162
+ ] }),
3163
+ /* @__PURE__ */ jsx40(Form, { ...form, children: /* @__PURE__ */ jsxs35("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
3164
+ /* @__PURE__ */ jsx40(FormInput, { form, id: "name", name: "Product Name", placeholder: "Enter product name", isRequired: true }),
3165
+ /* @__PURE__ */ jsx40(
3166
+ FormTextarea,
3167
+ {
3168
+ form,
3169
+ id: "description",
3170
+ name: "Description",
3171
+ placeholder: "Enter product description",
3172
+ className: "min-h-32"
3173
+ }
3174
+ ),
3175
+ /* @__PURE__ */ jsx40(FormCheckbox, { form, id: "active", name: "Active" }),
3176
+ /* @__PURE__ */ jsx40(CommonEditorButtons, { isEdit: !!product, form, disabled: isSubmitting, setOpen: onOpenChange })
3177
+ ] }) })
3178
+ ] }) });
3179
+ }
3180
+ __name(ProductEditor, "ProductEditor");
3181
+
3182
+ // src/features/billing/contexts/BillingContext.tsx
3183
+ import { jsx as jsx41 } from "react/jsx-runtime";
3184
+ var BillingContext = createContext(void 0);
3185
+ var BillingProvider = /* @__PURE__ */ __name(({ children }) => {
3186
+ const t = useTranslations();
3187
+ const { hasRole } = useCurrentUserContext();
3188
+ const [showCreateProduct, setShowCreateProduct] = useState16(false);
3189
+ const [refreshToken, setRefreshToken] = useState16(0);
3190
+ const refresh = useCallback5(() => setRefreshToken((value) => value + 1), []);
3191
+ const breadcrumbs = [{ name: t(`billing.admin.products.title`) }];
3192
+ const title = /* @__PURE__ */ __name(() => {
3193
+ const response = { type: t(`billing.admin.products.title`) };
3194
+ if (hasRole(getRoleId().Administrator)) {
3195
+ response.functions = [
3196
+ /* @__PURE__ */ jsx41(Button, { onClick: () => setShowCreateProduct(true), children: t(`billing.admin.products.create`) }, "productEditorTrigger"),
3197
+ showCreateProduct ? /* @__PURE__ */ jsx41(
3198
+ ProductEditor,
3199
+ {
3200
+ open: showCreateProduct,
3201
+ onOpenChange: setShowCreateProduct,
3202
+ onSuccess: () => {
3203
+ setShowCreateProduct(false);
3204
+ refresh();
3205
+ }
3206
+ },
3207
+ "productEditor"
3208
+ ) : null
3209
+ ];
3210
+ }
3211
+ return response;
3212
+ }, "title");
3213
+ return /* @__PURE__ */ jsx41(SharedProvider, { value: { breadcrumbs, title: title() }, children: /* @__PURE__ */ jsx41(BillingContext.Provider, { value: { refreshToken, refresh }, children }) });
3214
+ }, "BillingProvider");
3215
+ var useBillingContext = /* @__PURE__ */ __name(() => {
3216
+ const context = useContext(BillingContext);
3217
+ if (context === void 0) {
3218
+ throw new Error("useBillingContext must be used within a BillingProvider");
3219
+ }
3220
+ return context;
3221
+ }, "useBillingContext");
3222
+ var useOptionalBillingContext = /* @__PURE__ */ __name(() => useContext(BillingContext), "useOptionalBillingContext");
3223
+
3224
+ // src/features/billing/stripe-price/components/forms/PriceEditor.tsx
3225
+ import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
3226
+ import { AlertCircle as AlertCircle3, PlusIcon, XIcon } from "lucide-react";
3227
+ import { useEffect as useEffect10, useState as useState17 } from "react";
3228
+ import { useForm as useForm3 } from "react-hook-form";
3229
+ import { v4 as v43 } from "uuid";
3230
+ import { z as z3 } from "zod";
3231
+ import { jsx as jsx42, jsxs as jsxs36 } from "react/jsx-runtime";
3232
+ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3233
+ const [isSubmitting, setIsSubmitting] = useState17(false);
3234
+ const [allFeatures, setAllFeatures] = useState17([]);
3114
3235
  useEffect10(() => {
3115
3236
  const fetchFeatures = /* @__PURE__ */ __name(async () => {
3116
3237
  try {
@@ -3122,32 +3243,32 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3122
3243
  }, "fetchFeatures");
3123
3244
  fetchFeatures();
3124
3245
  }, []);
3125
- const formSchema2 = z2.object({
3126
- unitAmount: z2.preprocess(
3246
+ const formSchema2 = z3.object({
3247
+ unitAmount: z3.preprocess(
3127
3248
  (val) => typeof val === "string" ? parseFloat(val) : val,
3128
- z2.number().min(0, { message: "Amount must be 0 or greater" })
3249
+ z3.number().min(0, { message: "Amount must be 0 or greater" })
3129
3250
  ),
3130
- currency: z2.string().min(1, { message: "Currency is required" }),
3131
- interval: z2.enum(["one_time", "day", "week", "month", "year"]),
3132
- intervalCount: z2.preprocess(
3251
+ currency: z3.string().min(1, { message: "Currency is required" }),
3252
+ interval: z3.enum(["one_time", "day", "week", "month", "year"]),
3253
+ intervalCount: z3.preprocess(
3133
3254
  (val) => val === "" || val === void 0 ? void 0 : typeof val === "string" ? parseInt(val, 10) : val,
3134
- z2.number().min(1).optional()
3255
+ z3.number().min(1).optional()
3135
3256
  ),
3136
- usageType: z2.enum(["licensed", "metered"]).optional(),
3137
- nickname: z2.string().optional(),
3138
- active: z2.boolean(),
3139
- isTrial: z2.boolean(),
3140
- description: z2.string().optional(),
3141
- features: z2.array(z2.string()),
3142
- token: z2.string(),
3143
- featureIds: z2.array(z2.string())
3257
+ usageType: z3.enum(["licensed", "metered"]).optional(),
3258
+ nickname: z3.string().optional(),
3259
+ active: z3.boolean(),
3260
+ isTrial: z3.boolean(),
3261
+ description: z3.string().optional(),
3262
+ features: z3.array(z3.string()),
3263
+ token: z3.string(),
3264
+ featureIds: z3.array(z3.string())
3144
3265
  });
3145
3266
  const isEditMode = !!price;
3146
3267
  const defaultUnitAmount = price?.unitAmount ? price.unitAmount / 100 : 0;
3147
3268
  const coreFeatureIds = allFeatures.filter((f) => f.isCore).map((f) => f.id);
3148
3269
  const defaultFeatureIds = [.../* @__PURE__ */ new Set([...price?.priceFeatures?.map((f) => f.id) ?? [], ...coreFeatureIds])];
3149
- const form = useForm2({
3150
- resolver: zodResolver2(formSchema2),
3270
+ const form = useForm3({
3271
+ resolver: zodResolver3(formSchema2),
3151
3272
  defaultValues: {
3152
3273
  unitAmount: defaultUnitAmount,
3153
3274
  currency: price?.currency || "usd",
@@ -3203,7 +3324,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3203
3324
  });
3204
3325
  } else {
3205
3326
  const createInput = {
3206
- id: v42(),
3327
+ id: v43(),
3207
3328
  productId,
3208
3329
  currency: values.currency,
3209
3330
  unitAmount: unitAmountInCents
@@ -3260,21 +3381,21 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3260
3381
  { id: "licensed", text: "Licensed (per unit)" },
3261
3382
  { id: "metered", text: "Metered (usage-based)" }
3262
3383
  ];
3263
- return /* @__PURE__ */ jsx40(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs35(DialogContent, { className: "max-w-2xl", children: [
3264
- /* @__PURE__ */ jsxs35(DialogHeader, { children: [
3265
- /* @__PURE__ */ jsx40(DialogTitle, { children: isEditMode ? "Edit Price" : "Create Price" }),
3266
- /* @__PURE__ */ jsx40(DialogDescription, { children: isEditMode ? "Update the price details. Note: Only nickname and active status can be changed." : "Create a new price for this product" })
3384
+ return /* @__PURE__ */ jsx42(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs36(DialogContent, { className: "max-w-2xl", children: [
3385
+ /* @__PURE__ */ jsxs36(DialogHeader, { children: [
3386
+ /* @__PURE__ */ jsx42(DialogTitle, { children: isEditMode ? "Edit Price" : "Create Price" }),
3387
+ /* @__PURE__ */ jsx42(DialogDescription, { children: isEditMode ? "Update the price details. Note: Only nickname and active status can be changed." : "Create a new price for this product" })
3267
3388
  ] }),
3268
- isEditMode && /* @__PURE__ */ jsxs35("div", { className: "bg-primary/10 border-primary/30 flex gap-x-3 rounded-lg border p-4", children: [
3269
- /* @__PURE__ */ jsx40(AlertCircle3, { className: "text-primary mt-0.5 h-5 w-5 flex-shrink-0" }),
3270
- /* @__PURE__ */ jsxs35("div", { className: "text-foreground text-sm", children: [
3271
- /* @__PURE__ */ jsx40("p", { className: "font-semibold mb-1", children: "Stripe Price Immutability" }),
3272
- /* @__PURE__ */ jsx40("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." })
3389
+ isEditMode && /* @__PURE__ */ jsxs36("div", { className: "bg-primary/10 border-primary/30 flex gap-x-3 rounded-lg border p-4", children: [
3390
+ /* @__PURE__ */ jsx42(AlertCircle3, { className: "text-primary mt-0.5 h-5 w-5 flex-shrink-0" }),
3391
+ /* @__PURE__ */ jsxs36("div", { className: "text-foreground text-sm", children: [
3392
+ /* @__PURE__ */ jsx42("p", { className: "font-semibold mb-1", children: "Stripe Price Immutability" }),
3393
+ /* @__PURE__ */ jsx42("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." })
3273
3394
  ] })
3274
3395
  ] }),
3275
- /* @__PURE__ */ jsx40(Form, { ...form, children: /* @__PURE__ */ jsxs35("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
3276
- /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-x-4", children: [
3277
- /* @__PURE__ */ jsx40(
3396
+ /* @__PURE__ */ jsx42(Form, { ...form, children: /* @__PURE__ */ jsxs36("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
3397
+ /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-2 gap-x-4", children: [
3398
+ /* @__PURE__ */ jsx42(
3278
3399
  FormInput,
3279
3400
  {
3280
3401
  form,
@@ -3285,9 +3406,9 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3285
3406
  isRequired: true
3286
3407
  }
3287
3408
  ),
3288
- /* @__PURE__ */ jsx40(FormSelect, { form, id: "currency", name: "Currency", values: currencyOptions, disabled: isEditMode })
3409
+ /* @__PURE__ */ jsx42(FormSelect, { form, id: "currency", name: "Currency", values: currencyOptions, disabled: isEditMode })
3289
3410
  ] }),
3290
- /* @__PURE__ */ jsx40(
3411
+ /* @__PURE__ */ jsx42(
3291
3412
  FormSelect,
3292
3413
  {
3293
3414
  form,
@@ -3297,8 +3418,8 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3297
3418
  disabled: isEditMode
3298
3419
  }
3299
3420
  ),
3300
- isRecurring && /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-2 gap-x-4", children: [
3301
- /* @__PURE__ */ jsx40(
3421
+ isRecurring && /* @__PURE__ */ jsxs36("div", { className: "grid grid-cols-2 gap-x-4", children: [
3422
+ /* @__PURE__ */ jsx42(
3302
3423
  FormInput,
3303
3424
  {
3304
3425
  form,
@@ -3309,7 +3430,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3309
3430
  disabled: isEditMode
3310
3431
  }
3311
3432
  ),
3312
- /* @__PURE__ */ jsx40(
3433
+ /* @__PURE__ */ jsx42(
3313
3434
  FormSelect,
3314
3435
  {
3315
3436
  form,
@@ -3320,7 +3441,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3320
3441
  }
3321
3442
  )
3322
3443
  ] }),
3323
- /* @__PURE__ */ jsx40(
3444
+ /* @__PURE__ */ jsx42(
3324
3445
  FormInput,
3325
3446
  {
3326
3447
  form,
@@ -3329,7 +3450,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3329
3450
  placeholder: "e.g., Standard Plan, Pro Tier"
3330
3451
  }
3331
3452
  ),
3332
- /* @__PURE__ */ jsx40(
3453
+ /* @__PURE__ */ jsx42(
3333
3454
  FormTextarea,
3334
3455
  {
3335
3456
  form,
@@ -3339,12 +3460,12 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3339
3460
  className: "min-h-24"
3340
3461
  }
3341
3462
  ),
3342
- /* @__PURE__ */ jsx40(FormInput, { form, id: "token", name: "Token (optional)", placeholder: "Enter token value" }),
3343
- /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
3344
- /* @__PURE__ */ jsx40(Label, { children: "Features (optional)" }),
3345
- /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
3346
- form.watch("features").map((_, index) => /* @__PURE__ */ jsxs35("div", { className: "flex gap-2", children: [
3347
- /* @__PURE__ */ jsx40(
3463
+ /* @__PURE__ */ jsx42(FormInput, { form, id: "token", name: "Token (optional)", placeholder: "Enter token value" }),
3464
+ /* @__PURE__ */ jsxs36("div", { className: "space-y-2", children: [
3465
+ /* @__PURE__ */ jsx42(Label, { children: "Features (optional)" }),
3466
+ /* @__PURE__ */ jsxs36("div", { className: "space-y-2", children: [
3467
+ form.watch("features").map((_, index) => /* @__PURE__ */ jsxs36("div", { className: "flex gap-2", children: [
3468
+ /* @__PURE__ */ jsx42(
3348
3469
  Input,
3349
3470
  {
3350
3471
  ...form.register(`features.${index}`),
@@ -3352,7 +3473,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3352
3473
  className: "flex-1"
3353
3474
  }
3354
3475
  ),
3355
- /* @__PURE__ */ jsx40(
3476
+ /* @__PURE__ */ jsx42(
3356
3477
  Button,
3357
3478
  {
3358
3479
  type: "button",
@@ -3365,11 +3486,11 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3365
3486
  currentFeatures.filter((_2, i) => i !== index)
3366
3487
  );
3367
3488
  },
3368
- children: /* @__PURE__ */ jsx40(XIcon, { className: "h-4 w-4" })
3489
+ children: /* @__PURE__ */ jsx42(XIcon, { className: "h-4 w-4" })
3369
3490
  }
3370
3491
  )
3371
3492
  ] }, index)),
3372
- /* @__PURE__ */ jsxs35(
3493
+ /* @__PURE__ */ jsxs36(
3373
3494
  Button,
3374
3495
  {
3375
3496
  type: "button",
@@ -3381,20 +3502,20 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3381
3502
  },
3382
3503
  className: "mt-2",
3383
3504
  children: [
3384
- /* @__PURE__ */ jsx40(PlusIcon, { className: "h-4 w-4 mr-2" }),
3505
+ /* @__PURE__ */ jsx42(PlusIcon, { className: "h-4 w-4 mr-2" }),
3385
3506
  "Add Feature"
3386
3507
  ]
3387
3508
  }
3388
3509
  )
3389
3510
  ] })
3390
3511
  ] }),
3391
- isRecurring && allFeatures.length > 0 && /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
3392
- /* @__PURE__ */ jsx40(Label, { children: "Platform Features" }),
3393
- /* @__PURE__ */ jsx40("div", { className: "border rounded-md p-4 space-y-2 max-h-48 overflow-y-auto", children: allFeatures.map((feature) => {
3512
+ isRecurring && allFeatures.length > 0 && /* @__PURE__ */ jsxs36("div", { className: "space-y-2", children: [
3513
+ /* @__PURE__ */ jsx42(Label, { children: "Platform Features" }),
3514
+ /* @__PURE__ */ jsx42("div", { className: "border rounded-md p-4 space-y-2 max-h-48 overflow-y-auto", children: allFeatures.map((feature) => {
3394
3515
  const isCore = feature.isCore;
3395
3516
  const isChecked = form.watch("featureIds").includes(feature.id);
3396
- return /* @__PURE__ */ jsxs35("div", { className: "flex items-center space-x-2", children: [
3397
- /* @__PURE__ */ jsx40(
3517
+ return /* @__PURE__ */ jsxs36("div", { className: "flex items-center space-x-2", children: [
3518
+ /* @__PURE__ */ jsx42(
3398
3519
  "input",
3399
3520
  {
3400
3521
  type: "checkbox",
@@ -3417,22 +3538,22 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3417
3538
  className: "h-4 w-4 rounded border-gray-300 text-primary focus:ring-primary disabled:opacity-50"
3418
3539
  }
3419
3540
  ),
3420
- /* @__PURE__ */ jsxs35(
3541
+ /* @__PURE__ */ jsxs36(
3421
3542
  "label",
3422
3543
  {
3423
3544
  htmlFor: `feature-${feature.id}`,
3424
3545
  className: `text-sm ${isCore ? "text-muted-foreground" : ""}`,
3425
3546
  children: [
3426
3547
  feature.name,
3427
- isCore && /* @__PURE__ */ jsx40("span", { className: "ml-2 text-xs text-muted-foreground", children: "(Core - Required)" })
3548
+ isCore && /* @__PURE__ */ jsx42("span", { className: "ml-2 text-xs text-muted-foreground", children: "(Core - Required)" })
3428
3549
  ]
3429
3550
  }
3430
3551
  )
3431
3552
  ] }, feature.id);
3432
3553
  }) })
3433
3554
  ] }),
3434
- /* @__PURE__ */ jsx40(FormCheckbox, { form, id: "active", name: "Active" }),
3435
- isRecurring && /* @__PURE__ */ jsx40(
3555
+ /* @__PURE__ */ jsx42(FormCheckbox, { form, id: "active", name: "Active" }),
3556
+ isRecurring && /* @__PURE__ */ jsx42(
3436
3557
  FormCheckbox,
3437
3558
  {
3438
3559
  form,
@@ -3441,7 +3562,7 @@ function PriceEditor({ productId, price, open, onOpenChange, onSuccess }) {
3441
3562
  description: "Mark this as the trial subscription plan (only one price should be marked as trial)"
3442
3563
  }
3443
3564
  ),
3444
- /* @__PURE__ */ jsx40(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
3565
+ /* @__PURE__ */ jsx42(CommonEditorButtons, { isEdit: isEditMode, form, disabled: isSubmitting, setOpen: onOpenChange })
3445
3566
  ] }) })
3446
3567
  ] }) });
3447
3568
  }
@@ -3449,17 +3570,17 @@ __name(PriceEditor, "PriceEditor");
3449
3570
 
3450
3571
  // src/features/billing/stripe-price/components/lists/PricesList.tsx
3451
3572
  import { Archive, DollarSign, Edit, RotateCcw } from "lucide-react";
3452
- import { useEffect as useEffect11, useState as useState16 } from "react";
3453
- import { jsx as jsx41, jsxs as jsxs36 } from "react/jsx-runtime";
3573
+ import { useEffect as useEffect11, useState as useState18 } from "react";
3574
+ import { jsx as jsx43, jsxs as jsxs37 } from "react/jsx-runtime";
3454
3575
  function PricesList({ productId, onPricesChange }) {
3455
- const [prices, setPrices] = useState16([]);
3456
- const [loading, setLoading] = useState16(true);
3457
- const [showCreatePrice, setShowCreatePrice] = useState16(false);
3458
- const [editingPrice, setEditingPrice] = useState16(null);
3459
- const [priceToArchive, setPriceToArchive] = useState16(null);
3460
- const [priceToReactivate, setPriceToReactivate] = useState16(null);
3461
- const [archivingPriceId, setArchivingPriceId] = useState16(null);
3462
- const [reactivatingPriceId, setReactivatingPriceId] = useState16(null);
3576
+ const [prices, setPrices] = useState18([]);
3577
+ const [loading, setLoading] = useState18(true);
3578
+ const [showCreatePrice, setShowCreatePrice] = useState18(false);
3579
+ const [editingPrice, setEditingPrice] = useState18(null);
3580
+ const [priceToArchive, setPriceToArchive] = useState18(null);
3581
+ const [priceToReactivate, setPriceToReactivate] = useState18(null);
3582
+ const [archivingPriceId, setArchivingPriceId] = useState18(null);
3583
+ const [reactivatingPriceId, setReactivatingPriceId] = useState18(null);
3463
3584
  const loadPrices = /* @__PURE__ */ __name(async () => {
3464
3585
  setLoading(true);
3465
3586
  try {
@@ -3522,27 +3643,27 @@ function PricesList({ productId, onPricesChange }) {
3522
3643
  return "";
3523
3644
  }, "formatInterval");
3524
3645
  if (loading) {
3525
- return /* @__PURE__ */ jsx41("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx41("p", { className: "text-muted-foreground", children: "Loading prices..." }) });
3646
+ return /* @__PURE__ */ jsx43("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx43("p", { className: "text-muted-foreground", children: "Loading prices..." }) });
3526
3647
  }
3527
- return /* @__PURE__ */ jsxs36("div", { className: "flex flex-col gap-y-4", children: [
3528
- /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between mb-4", children: [
3529
- /* @__PURE__ */ jsx41("h4", { className: "text-lg font-semibold", children: "Prices" }),
3530
- /* @__PURE__ */ jsx41(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
3648
+ return /* @__PURE__ */ jsxs37("div", { className: "flex flex-col gap-y-4", children: [
3649
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-center justify-between mb-4", children: [
3650
+ /* @__PURE__ */ jsx43("h4", { className: "text-lg font-semibold", children: "Prices" }),
3651
+ /* @__PURE__ */ jsx43(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
3531
3652
  ] }),
3532
- prices.length === 0 && /* @__PURE__ */ jsxs36("div", { className: "bg-background flex flex-col items-center justify-center gap-y-3 rounded-lg border border-dashed p-8", children: [
3533
- /* @__PURE__ */ jsx41(DollarSign, { className: "text-muted-foreground h-12 w-12" }),
3534
- /* @__PURE__ */ jsx41("p", { className: "text-muted-foreground text-sm", children: "No prices yet. Add a price to enable subscriptions." }),
3535
- /* @__PURE__ */ jsx41(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
3653
+ prices.length === 0 && /* @__PURE__ */ jsxs37("div", { className: "bg-background flex flex-col items-center justify-center gap-y-3 rounded-lg border border-dashed p-8", children: [
3654
+ /* @__PURE__ */ jsx43(DollarSign, { className: "text-muted-foreground h-12 w-12" }),
3655
+ /* @__PURE__ */ jsx43("p", { className: "text-muted-foreground text-sm", children: "No prices yet. Add a price to enable subscriptions." }),
3656
+ /* @__PURE__ */ jsx43(Button, { size: "sm", onClick: () => setShowCreatePrice(true), children: "Add Price" })
3536
3657
  ] }),
3537
- prices.length > 0 && /* @__PURE__ */ jsx41("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: prices.map((price) => {
3658
+ prices.length > 0 && /* @__PURE__ */ jsx43("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: prices.map((price) => {
3538
3659
  const isArchiving = archivingPriceId === price.id;
3539
3660
  const isReactivating = reactivatingPriceId === price.id;
3540
- return /* @__PURE__ */ jsxs36("div", { className: "border rounded-lg bg-white p-4 hover:shadow-sm transition-shadow", children: [
3541
- /* @__PURE__ */ jsxs36("div", { className: "flex items-start justify-between mb-3", children: [
3542
- /* @__PURE__ */ jsx41(DollarSign, { className: "h-5 w-5 text-primary" }),
3543
- /* @__PURE__ */ jsxs36("div", { className: "flex gap-1", children: [
3544
- /* @__PURE__ */ jsx41(Button, { variant: "ghost", size: "sm", onClick: () => setEditingPrice(price), className: "h-8 w-8 p-0", children: /* @__PURE__ */ jsx41(Edit, { className: "h-4 w-4" }) }),
3545
- price.active ? /* @__PURE__ */ jsx41(
3661
+ return /* @__PURE__ */ jsxs37("div", { className: "border rounded-lg bg-white p-4 hover:shadow-sm transition-shadow", children: [
3662
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-start justify-between mb-3", children: [
3663
+ /* @__PURE__ */ jsx43(DollarSign, { className: "h-5 w-5 text-primary" }),
3664
+ /* @__PURE__ */ jsxs37("div", { className: "flex gap-1", children: [
3665
+ /* @__PURE__ */ jsx43(Button, { variant: "ghost", size: "sm", onClick: () => setEditingPrice(price), className: "h-8 w-8 p-0", children: /* @__PURE__ */ jsx43(Edit, { className: "h-4 w-4" }) }),
3666
+ price.active ? /* @__PURE__ */ jsx43(
3546
3667
  Button,
3547
3668
  {
3548
3669
  variant: "ghost",
@@ -3550,9 +3671,9 @@ function PricesList({ productId, onPricesChange }) {
3550
3671
  onClick: () => setPriceToArchive(price),
3551
3672
  className: "h-8 w-8 p-0",
3552
3673
  disabled: isArchiving,
3553
- children: /* @__PURE__ */ jsx41(Archive, { className: "h-4 w-4" })
3674
+ children: /* @__PURE__ */ jsx43(Archive, { className: "h-4 w-4" })
3554
3675
  }
3555
- ) : /* @__PURE__ */ jsx41(
3676
+ ) : /* @__PURE__ */ jsx43(
3556
3677
  Button,
3557
3678
  {
3558
3679
  variant: "ghost",
@@ -3560,25 +3681,25 @@ function PricesList({ productId, onPricesChange }) {
3560
3681
  onClick: () => setPriceToReactivate(price),
3561
3682
  className: "h-8 w-8 p-0",
3562
3683
  disabled: isReactivating,
3563
- children: /* @__PURE__ */ jsx41(RotateCcw, { className: "h-4 w-4" })
3684
+ children: /* @__PURE__ */ jsx43(RotateCcw, { className: "h-4 w-4" })
3564
3685
  }
3565
3686
  )
3566
3687
  ] })
3567
3688
  ] }),
3568
- /* @__PURE__ */ jsx41("div", { className: "mb-2", children: /* @__PURE__ */ jsxs36("div", { className: "text-2xl font-bold", children: [
3689
+ /* @__PURE__ */ jsx43("div", { className: "mb-2", children: /* @__PURE__ */ jsxs37("div", { className: "text-2xl font-bold", children: [
3569
3690
  formatCurrency(price.unitAmount, price.currency),
3570
3691
  " ",
3571
- /* @__PURE__ */ jsx41("span", { className: "text-muted-foreground text-sm font-normal", children: formatInterval2(price) })
3692
+ /* @__PURE__ */ jsx43("span", { className: "text-muted-foreground text-sm font-normal", children: formatInterval2(price) })
3572
3693
  ] }) }),
3573
- price.metadata?.nickname && /* @__PURE__ */ jsx41("p", { className: "text-sm font-medium mb-2", children: price.metadata.nickname }),
3574
- /* @__PURE__ */ jsxs36("div", { className: "flex flex-wrap gap-2", children: [
3575
- price.active ? /* @__PURE__ */ jsx41(Badge, { variant: "softGreen", children: "Active" }) : /* @__PURE__ */ jsx41(Badge, { variant: "softGray", children: "Inactive" }),
3576
- price.recurring?.usageType === "metered" && /* @__PURE__ */ jsx41(Badge, { variant: "softBlue", children: "Metered" }),
3577
- /* @__PURE__ */ jsx41(Badge, { variant: "softGray", className: "uppercase", children: price.currency })
3694
+ price.metadata?.nickname && /* @__PURE__ */ jsx43("p", { className: "text-sm font-medium mb-2", children: price.metadata.nickname }),
3695
+ /* @__PURE__ */ jsxs37("div", { className: "flex flex-wrap gap-2", children: [
3696
+ price.active ? /* @__PURE__ */ jsx43(Badge, { variant: "softGreen", children: "Active" }) : /* @__PURE__ */ jsx43(Badge, { variant: "softGray", children: "Inactive" }),
3697
+ price.recurring?.usageType === "metered" && /* @__PURE__ */ jsx43(Badge, { variant: "softBlue", children: "Metered" }),
3698
+ /* @__PURE__ */ jsx43(Badge, { variant: "softGray", className: "uppercase", children: price.currency })
3578
3699
  ] })
3579
3700
  ] }, price.id);
3580
3701
  }) }),
3581
- showCreatePrice && /* @__PURE__ */ jsx41(
3702
+ showCreatePrice && /* @__PURE__ */ jsx43(
3582
3703
  PriceEditor,
3583
3704
  {
3584
3705
  productId,
@@ -3590,7 +3711,7 @@ function PricesList({ productId, onPricesChange }) {
3590
3711
  }
3591
3712
  }
3592
3713
  ),
3593
- editingPrice && /* @__PURE__ */ jsx41(
3714
+ editingPrice && /* @__PURE__ */ jsx43(
3594
3715
  PriceEditor,
3595
3716
  {
3596
3717
  productId,
@@ -3604,19 +3725,19 @@ function PricesList({ productId, onPricesChange }) {
3604
3725
  }
3605
3726
  }
3606
3727
  ),
3607
- /* @__PURE__ */ jsx41(AlertDialog, { open: !!priceToArchive, onOpenChange: (open) => !open && setPriceToArchive(null), children: /* @__PURE__ */ jsxs36(AlertDialogContent, { children: [
3608
- /* @__PURE__ */ jsxs36(AlertDialogHeader, { children: [
3609
- /* @__PURE__ */ jsx41(AlertDialogTitle, { children: "Archive Price" }),
3610
- /* @__PURE__ */ jsxs36(AlertDialogDescription, { children: [
3728
+ /* @__PURE__ */ jsx43(AlertDialog, { open: !!priceToArchive, onOpenChange: (open) => !open && setPriceToArchive(null), children: /* @__PURE__ */ jsxs37(AlertDialogContent, { children: [
3729
+ /* @__PURE__ */ jsxs37(AlertDialogHeader, { children: [
3730
+ /* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Archive Price" }),
3731
+ /* @__PURE__ */ jsxs37(AlertDialogDescription, { children: [
3611
3732
  "Are you sure you want to archive the price for",
3612
3733
  " ",
3613
3734
  priceToArchive && `${formatCurrency(priceToArchive.unitAmount, priceToArchive.currency)} ${formatInterval2(priceToArchive)}`,
3614
3735
  "? This will prevent new subscriptions but existing ones will continue."
3615
3736
  ] })
3616
3737
  ] }),
3617
- /* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
3618
- /* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!archivingPriceId, children: "Cancel" }),
3619
- /* @__PURE__ */ jsx41(
3738
+ /* @__PURE__ */ jsxs37(AlertDialogFooter, { children: [
3739
+ /* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!archivingPriceId, children: "Cancel" }),
3740
+ /* @__PURE__ */ jsx43(
3620
3741
  AlertDialogAction,
3621
3742
  {
3622
3743
  onClick: handleArchive,
@@ -3627,19 +3748,19 @@ function PricesList({ productId, onPricesChange }) {
3627
3748
  )
3628
3749
  ] })
3629
3750
  ] }) }),
3630
- /* @__PURE__ */ jsx41(AlertDialog, { open: !!priceToReactivate, onOpenChange: (open) => !open && setPriceToReactivate(null), children: /* @__PURE__ */ jsxs36(AlertDialogContent, { children: [
3631
- /* @__PURE__ */ jsxs36(AlertDialogHeader, { children: [
3632
- /* @__PURE__ */ jsx41(AlertDialogTitle, { children: "Reactivate Price" }),
3633
- /* @__PURE__ */ jsxs36(AlertDialogDescription, { children: [
3751
+ /* @__PURE__ */ jsx43(AlertDialog, { open: !!priceToReactivate, onOpenChange: (open) => !open && setPriceToReactivate(null), children: /* @__PURE__ */ jsxs37(AlertDialogContent, { children: [
3752
+ /* @__PURE__ */ jsxs37(AlertDialogHeader, { children: [
3753
+ /* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Reactivate Price" }),
3754
+ /* @__PURE__ */ jsxs37(AlertDialogDescription, { children: [
3634
3755
  "Are you sure you want to reactivate the price for",
3635
3756
  " ",
3636
3757
  priceToReactivate && `${formatCurrency(priceToReactivate.unitAmount, priceToReactivate.currency)} ${formatInterval2(priceToReactivate)}`,
3637
3758
  "? This will allow new subscriptions again."
3638
3759
  ] })
3639
3760
  ] }),
3640
- /* @__PURE__ */ jsxs36(AlertDialogFooter, { children: [
3641
- /* @__PURE__ */ jsx41(AlertDialogCancel, { disabled: !!reactivatingPriceId, children: "Cancel" }),
3642
- /* @__PURE__ */ jsx41(
3761
+ /* @__PURE__ */ jsxs37(AlertDialogFooter, { children: [
3762
+ /* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!reactivatingPriceId, children: "Cancel" }),
3763
+ /* @__PURE__ */ jsx43(
3643
3764
  AlertDialogAction,
3644
3765
  {
3645
3766
  onClick: handleReactivate,
@@ -3656,91 +3777,19 @@ __name(PricesList, "PricesList");
3656
3777
 
3657
3778
  // src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
3658
3779
  import { Package as Package2 } from "lucide-react";
3659
- import { useEffect as useEffect12, useState as useState19 } from "react";
3660
-
3661
- // src/features/billing/stripe-product/components/forms/ProductEditor.tsx
3662
- import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
3663
- import { useState as useState17 } from "react";
3664
- import { useForm as useForm3 } from "react-hook-form";
3665
- import { v4 as v43 } from "uuid";
3666
- import { z as z3 } from "zod";
3667
- import { jsx as jsx42, jsxs as jsxs37 } from "react/jsx-runtime";
3668
- function ProductEditor({ product, open, onOpenChange, onSuccess }) {
3669
- const [isSubmitting, setIsSubmitting] = useState17(false);
3670
- const formSchema2 = z3.object({
3671
- name: z3.string().min(1, { message: "Product name is required" }),
3672
- description: z3.string().min(1, { message: "Description is required" }),
3673
- active: z3.boolean()
3674
- });
3675
- const form = useForm3({
3676
- resolver: zodResolver3(formSchema2),
3677
- defaultValues: {
3678
- name: product?.name || "",
3679
- description: product?.description || "",
3680
- active: product?.active ?? true
3681
- }
3682
- });
3683
- const onSubmit = /* @__PURE__ */ __name(async (values) => {
3684
- setIsSubmitting(true);
3685
- try {
3686
- if (product) {
3687
- await StripeProductService.updateProduct({
3688
- id: product.id,
3689
- name: values.name,
3690
- description: values.description,
3691
- active: values.active
3692
- });
3693
- } else {
3694
- await StripeProductService.createProduct({
3695
- id: v43(),
3696
- name: values.name,
3697
- description: values.description,
3698
- active: values.active
3699
- });
3700
- }
3701
- onSuccess();
3702
- onOpenChange(false);
3703
- } catch (error) {
3704
- console.error("[ProductEditor] Failed to save product:", error);
3705
- } finally {
3706
- setIsSubmitting(false);
3707
- }
3708
- }, "onSubmit");
3709
- return /* @__PURE__ */ jsx42(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs37(DialogContent, { className: "max-w-2xl", children: [
3710
- /* @__PURE__ */ jsxs37(DialogHeader, { children: [
3711
- /* @__PURE__ */ jsx42(DialogTitle, { children: product ? "Edit Product" : "Create Product" }),
3712
- /* @__PURE__ */ jsx42(DialogDescription, { children: product ? `Update the details for ${product.name}` : "Create a new product to offer to your customers" })
3713
- ] }),
3714
- /* @__PURE__ */ jsx42(Form, { ...form, children: /* @__PURE__ */ jsxs37("form", { onSubmit: form.handleSubmit(onSubmit), className: "flex flex-col gap-y-4", children: [
3715
- /* @__PURE__ */ jsx42(FormInput, { form, id: "name", name: "Product Name", placeholder: "Enter product name", isRequired: true }),
3716
- /* @__PURE__ */ jsx42(
3717
- FormTextarea,
3718
- {
3719
- form,
3720
- id: "description",
3721
- name: "Description",
3722
- placeholder: "Enter product description",
3723
- className: "min-h-32"
3724
- }
3725
- ),
3726
- /* @__PURE__ */ jsx42(FormCheckbox, { form, id: "active", name: "Active" }),
3727
- /* @__PURE__ */ jsx42(CommonEditorButtons, { isEdit: !!product, form, disabled: isSubmitting, setOpen: onOpenChange })
3728
- ] }) })
3729
- ] }) });
3730
- }
3731
- __name(ProductEditor, "ProductEditor");
3780
+ import { useEffect as useEffect12, useState as useState20 } from "react";
3732
3781
 
3733
3782
  // src/features/billing/stripe-product/components/lists/ProductsList.tsx
3734
3783
  import { Archive as Archive2, ChevronDown, ChevronUp, Edit as Edit2, Package, RefreshCw as RefreshCw2 } from "lucide-react";
3735
- import { useState as useState18 } from "react";
3736
- import { jsx as jsx43, jsxs as jsxs38 } from "react/jsx-runtime";
3784
+ import { useState as useState19 } from "react";
3785
+ import { jsx as jsx44, jsxs as jsxs38 } from "react/jsx-runtime";
3737
3786
  function ProductsList({ products, onProductsChange }) {
3738
- const [expandedProductId, setExpandedProductId] = useState18(null);
3739
- const [editingProduct, setEditingProduct] = useState18(null);
3740
- const [archivingProductId, setArchivingProductId] = useState18(null);
3741
- const [reactivatingProductId, setReactivatingProductId] = useState18(null);
3742
- const [productToArchive, setProductToArchive] = useState18(null);
3743
- const [productToReactivate, setProductToReactivate] = useState18(null);
3787
+ const [expandedProductId, setExpandedProductId] = useState19(null);
3788
+ const [editingProduct, setEditingProduct] = useState19(null);
3789
+ const [archivingProductId, setArchivingProductId] = useState19(null);
3790
+ const [reactivatingProductId, setReactivatingProductId] = useState19(null);
3791
+ const [productToArchive, setProductToArchive] = useState19(null);
3792
+ const [productToReactivate, setProductToReactivate] = useState19(null);
3744
3793
  const handleArchive = /* @__PURE__ */ __name(async () => {
3745
3794
  if (!productToArchive) {
3746
3795
  return;
@@ -3781,18 +3830,18 @@ function ProductsList({ products, onProductsChange }) {
3781
3830
  return /* @__PURE__ */ jsxs38("div", { className: "border rounded-lg bg-white shadow-sm hover:shadow-md transition-shadow", children: [
3782
3831
  /* @__PURE__ */ jsxs38("div", { className: "flex items-center justify-between p-6", children: [
3783
3832
  /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-4 flex-1", children: [
3784
- /* @__PURE__ */ jsx43(Package, { className: "h-6 w-6 text-primary" }),
3833
+ /* @__PURE__ */ jsx44(Package, { className: "h-6 w-6 text-primary" }),
3785
3834
  /* @__PURE__ */ jsxs38("div", { className: "flex-1", children: [
3786
3835
  /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-3", children: [
3787
- /* @__PURE__ */ jsx43("h3", { className: "text-sm font-medium", children: product.name }),
3788
- product.active ? /* @__PURE__ */ jsx43(Badge, { variant: "softGreen", children: "Active" }) : /* @__PURE__ */ jsx43(Badge, { variant: "softGray", children: "Inactive" })
3836
+ /* @__PURE__ */ jsx44("h3", { className: "text-sm font-medium", children: product.name }),
3837
+ product.active ? /* @__PURE__ */ jsx44(Badge, { variant: "softGreen", children: "Active" }) : /* @__PURE__ */ jsx44(Badge, { variant: "softGray", children: "Inactive" })
3789
3838
  ] }),
3790
- product.description && /* @__PURE__ */ jsx43("p", { className: "text-muted-foreground text-sm mt-1", children: product.description })
3839
+ product.description && /* @__PURE__ */ jsx44("p", { className: "text-muted-foreground text-sm mt-1", children: product.description })
3791
3840
  ] })
3792
3841
  ] }),
3793
3842
  /* @__PURE__ */ jsxs38("div", { className: "flex items-center gap-x-2", children: [
3794
3843
  /* @__PURE__ */ jsxs38(Button, { variant: "outline", size: "sm", onClick: () => setEditingProduct(product), children: [
3795
- /* @__PURE__ */ jsx43(Edit2, { className: "h-4 w-4 mr-1" }),
3844
+ /* @__PURE__ */ jsx44(Edit2, { className: "h-4 w-4 mr-1" }),
3796
3845
  "Edit"
3797
3846
  ] }),
3798
3847
  product.active ? /* @__PURE__ */ jsxs38(
@@ -3803,7 +3852,7 @@ function ProductsList({ products, onProductsChange }) {
3803
3852
  onClick: () => setProductToArchive(product),
3804
3853
  disabled: isArchiving,
3805
3854
  children: [
3806
- /* @__PURE__ */ jsx43(Archive2, { className: "h-4 w-4 mr-1" }),
3855
+ /* @__PURE__ */ jsx44(Archive2, { className: "h-4 w-4 mr-1" }),
3807
3856
  isArchiving ? "Archiving..." : "Archive"
3808
3857
  ]
3809
3858
  }
@@ -3815,18 +3864,18 @@ function ProductsList({ products, onProductsChange }) {
3815
3864
  onClick: () => setProductToReactivate(product),
3816
3865
  disabled: isReactivating,
3817
3866
  children: [
3818
- /* @__PURE__ */ jsx43(RefreshCw2, { className: "h-4 w-4 mr-1" }),
3867
+ /* @__PURE__ */ jsx44(RefreshCw2, { className: "h-4 w-4 mr-1" }),
3819
3868
  isReactivating ? "Reactivating..." : "Reactivate"
3820
3869
  ]
3821
3870
  }
3822
3871
  ),
3823
- /* @__PURE__ */ jsx43(Button, { variant: "ghost", size: "sm", onClick: () => toggleExpand(product.id), children: isExpanded ? /* @__PURE__ */ jsx43(ChevronUp, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx43(ChevronDown, { className: "h-5 w-5" }) })
3872
+ /* @__PURE__ */ jsx44(Button, { variant: "ghost", size: "sm", onClick: () => toggleExpand(product.id), children: isExpanded ? /* @__PURE__ */ jsx44(ChevronUp, { className: "h-5 w-5" }) : /* @__PURE__ */ jsx44(ChevronDown, { className: "h-5 w-5" }) })
3824
3873
  ] })
3825
3874
  ] }),
3826
- isExpanded && /* @__PURE__ */ jsx43("div", { className: "border-t bg-muted/30 p-6", children: /* @__PURE__ */ jsx43(PricesList, { productId: product.id, onPricesChange: onProductsChange }) })
3875
+ isExpanded && /* @__PURE__ */ jsx44("div", { className: "border-t bg-muted/30 p-6", children: /* @__PURE__ */ jsx44(PricesList, { productId: product.id, onPricesChange: onProductsChange }) })
3827
3876
  ] }, product.id);
3828
3877
  }),
3829
- editingProduct && /* @__PURE__ */ jsx43(
3878
+ editingProduct && /* @__PURE__ */ jsx44(
3830
3879
  ProductEditor,
3831
3880
  {
3832
3881
  product: editingProduct,
@@ -3838,9 +3887,9 @@ function ProductsList({ products, onProductsChange }) {
3838
3887
  }
3839
3888
  }
3840
3889
  ),
3841
- /* @__PURE__ */ jsx43(AlertDialog, { open: !!productToArchive, onOpenChange: (open) => !open && setProductToArchive(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
3890
+ /* @__PURE__ */ jsx44(AlertDialog, { open: !!productToArchive, onOpenChange: (open) => !open && setProductToArchive(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
3842
3891
  /* @__PURE__ */ jsxs38(AlertDialogHeader, { children: [
3843
- /* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Archive Product" }),
3892
+ /* @__PURE__ */ jsx44(AlertDialogTitle, { children: "Archive Product" }),
3844
3893
  /* @__PURE__ */ jsxs38(AlertDialogDescription, { children: [
3845
3894
  'Are you sure you want to archive "',
3846
3895
  productToArchive?.name,
@@ -3848,8 +3897,8 @@ function ProductsList({ products, onProductsChange }) {
3848
3897
  ] })
3849
3898
  ] }),
3850
3899
  /* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
3851
- /* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!archivingProductId, children: "Cancel" }),
3852
- /* @__PURE__ */ jsx43(
3900
+ /* @__PURE__ */ jsx44(AlertDialogCancel, { disabled: !!archivingProductId, children: "Cancel" }),
3901
+ /* @__PURE__ */ jsx44(
3853
3902
  AlertDialogAction,
3854
3903
  {
3855
3904
  onClick: handleArchive,
@@ -3860,9 +3909,9 @@ function ProductsList({ products, onProductsChange }) {
3860
3909
  )
3861
3910
  ] })
3862
3911
  ] }) }),
3863
- /* @__PURE__ */ jsx43(AlertDialog, { open: !!productToReactivate, onOpenChange: (open) => !open && setProductToReactivate(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
3912
+ /* @__PURE__ */ jsx44(AlertDialog, { open: !!productToReactivate, onOpenChange: (open) => !open && setProductToReactivate(null), children: /* @__PURE__ */ jsxs38(AlertDialogContent, { children: [
3864
3913
  /* @__PURE__ */ jsxs38(AlertDialogHeader, { children: [
3865
- /* @__PURE__ */ jsx43(AlertDialogTitle, { children: "Reactivate Product" }),
3914
+ /* @__PURE__ */ jsx44(AlertDialogTitle, { children: "Reactivate Product" }),
3866
3915
  /* @__PURE__ */ jsxs38(AlertDialogDescription, { children: [
3867
3916
  'Are you sure you want to reactivate "',
3868
3917
  productToReactivate?.name,
@@ -3870,8 +3919,8 @@ function ProductsList({ products, onProductsChange }) {
3870
3919
  ] })
3871
3920
  ] }),
3872
3921
  /* @__PURE__ */ jsxs38(AlertDialogFooter, { children: [
3873
- /* @__PURE__ */ jsx43(AlertDialogCancel, { disabled: !!reactivatingProductId, children: "Cancel" }),
3874
- /* @__PURE__ */ jsx43(
3922
+ /* @__PURE__ */ jsx44(AlertDialogCancel, { disabled: !!reactivatingProductId, children: "Cancel" }),
3923
+ /* @__PURE__ */ jsx44(
3875
3924
  AlertDialogAction,
3876
3925
  {
3877
3926
  onClick: handleReactivate,
@@ -3887,14 +3936,15 @@ function ProductsList({ products, onProductsChange }) {
3887
3936
  __name(ProductsList, "ProductsList");
3888
3937
 
3889
3938
  // src/features/billing/stripe-product/components/containers/ProductsAdminContainer.tsx
3890
- import { jsx as jsx44, jsxs as jsxs39 } from "react/jsx-runtime";
3939
+ import { jsx as jsx45, jsxs as jsxs39 } from "react/jsx-runtime";
3891
3940
  function ProductsAdminContainer() {
3892
3941
  const { hasRole } = useCurrentUserContext();
3893
- const [products, setProducts] = useState19([]);
3894
- const [loading, setLoading] = useState19(true);
3895
- const [showCreateProduct, setShowCreateProduct] = useState19(false);
3942
+ const billing = useOptionalBillingContext();
3943
+ const [products, setProducts] = useState20([]);
3944
+ const [loading, setLoading] = useState20(true);
3945
+ const [showCreateProduct, setShowCreateProduct] = useState20(false);
3896
3946
  if (!hasRole(getRoleId().Administrator)) {
3897
- return /* @__PURE__ */ jsx44("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx44("p", { className: "text-destructive text-xs/relaxed", children: "Permission denied. Administrator access required." }) });
3947
+ return /* @__PURE__ */ jsx45("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx45("p", { className: "text-destructive text-xs/relaxed", children: "Permission denied. Administrator access required." }) });
3898
3948
  }
3899
3949
  const loadProducts = /* @__PURE__ */ __name(async () => {
3900
3950
  setLoading(true);
@@ -3909,35 +3959,39 @@ function ProductsAdminContainer() {
3909
3959
  }, "loadProducts");
3910
3960
  useEffect12(() => {
3911
3961
  loadProducts();
3912
- }, []);
3962
+ }, [billing?.refreshToken]);
3913
3963
  if (loading) {
3914
- return /* @__PURE__ */ jsx44("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx44("p", { className: "text-muted-foreground", children: "Loading products..." }) });
3964
+ return /* @__PURE__ */ jsx45("div", { className: "flex h-64 items-center justify-center", children: /* @__PURE__ */ jsx45("p", { className: "text-muted-foreground", children: "Loading products..." }) });
3915
3965
  }
3916
- return /* @__PURE__ */ jsxs39("div", { className: "flex w-full flex-col gap-y-6", children: [
3917
- /* @__PURE__ */ jsxs39("div", { className: "flex items-center justify-between", children: [
3918
- /* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-x-3", children: [
3919
- /* @__PURE__ */ jsx44(Package2, { className: "h-8 w-8" }),
3920
- /* @__PURE__ */ jsx44("h1", { className: "text-primary text-3xl font-semibold", children: "Product & Price Management" })
3966
+ return /* @__PURE__ */ jsxs39("div", { className: "flex w-full flex-col", children: [
3967
+ !billing && /* @__PURE__ */ jsx45("div", { className: "flex w-full items-center justify-end px-4 pt-4", children: /* @__PURE__ */ jsx45(Button, { onClick: () => setShowCreateProduct(true), children: "Create Product" }) }),
3968
+ /* @__PURE__ */ jsxs39("div", { className: "flex w-full flex-col gap-y-6 px-4 pb-4", children: [
3969
+ products.length === 0 && /* @__PURE__ */ jsxs39("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed p-12", children: [
3970
+ /* @__PURE__ */ jsx45(Package2, { className: "text-muted-foreground h-16 w-16" }),
3971
+ /* @__PURE__ */ jsxs39("div", { className: "text-center", children: [
3972
+ /* @__PURE__ */ jsx45("h3", { className: "mb-2 text-sm font-medium", children: "No products yet" }),
3973
+ /* @__PURE__ */ jsx45("p", { className: "text-muted-foreground mb-4", children: "Create your first product to start offering subscriptions to your customers." }),
3974
+ /* @__PURE__ */ jsx45(Button, { onClick: () => setShowCreateProduct(true), children: "Create Your First Product" })
3975
+ ] })
3921
3976
  ] }),
3922
- /* @__PURE__ */ jsx44(Button, { onClick: () => setShowCreateProduct(true), children: "Create Product" })
3923
- ] }),
3924
- products.length === 0 && /* @__PURE__ */ jsxs39("div", { className: "bg-muted/50 flex flex-col items-center justify-center gap-y-4 rounded-lg border-2 border-dashed p-12", children: [
3925
- /* @__PURE__ */ jsx44(Package2, { className: "text-muted-foreground h-16 w-16" }),
3926
- /* @__PURE__ */ jsxs39("div", { className: "text-center", children: [
3927
- /* @__PURE__ */ jsx44("h3", { className: "mb-2 text-sm font-medium", children: "No products yet" }),
3928
- /* @__PURE__ */ jsx44("p", { className: "text-muted-foreground mb-4", children: "Create your first product to start offering subscriptions to your customers." }),
3929
- /* @__PURE__ */ jsx44(Button, { onClick: () => setShowCreateProduct(true), children: "Create Your First Product" })
3930
- ] })
3931
- ] }),
3932
- products.length > 0 && /* @__PURE__ */ jsx44(ProductsList, { products, onProductsChange: loadProducts }),
3933
- showCreateProduct && /* @__PURE__ */ jsx44(ProductEditor, { open: showCreateProduct, onOpenChange: setShowCreateProduct, onSuccess: loadProducts })
3977
+ products.length > 0 && /* @__PURE__ */ jsx45(ProductsList, { products, onProductsChange: loadProducts }),
3978
+ showCreateProduct && /* @__PURE__ */ jsx45(ProductEditor, { open: showCreateProduct, onOpenChange: setShowCreateProduct, onSuccess: loadProducts })
3979
+ ] })
3934
3980
  ] });
3935
3981
  }
3936
3982
  __name(ProductsAdminContainer, "ProductsAdminContainer");
3983
+
3984
+ // src/features/billing/stripe-product/components/containers/ProductsAdminPageContainer.tsx
3985
+ import { jsx as jsx46 } from "react/jsx-runtime";
3986
+ function ProductsAdminPageContainer() {
3987
+ return /* @__PURE__ */ jsx46(BillingProvider, { children: /* @__PURE__ */ jsx46(RoundPageContainer, { module: Modules.StripeProduct, fullWidth: true, forceHeader: true, children: /* @__PURE__ */ jsx46(ProductsAdminContainer, {}) }) });
3988
+ }
3989
+ __name(ProductsAdminPageContainer, "ProductsAdminPageContainer");
3937
3990
  export {
3938
3991
  BillingAlertBanner,
3939
3992
  BillingDashboardContainer,
3940
3993
  BillingDetailModal,
3994
+ BillingProvider,
3941
3995
  BillingUsageSummaryCard,
3942
3996
  CancelSubscriptionDialog,
3943
3997
  CustomerInfoCard,
@@ -3960,6 +4014,7 @@ export {
3960
4014
  ProductPricingList,
3961
4015
  ProductPricingRow,
3962
4016
  ProductsAdminContainer,
4017
+ ProductsAdminPageContainer,
3963
4018
  ProductsList,
3964
4019
  PromoCodeInput,
3965
4020
  ProrationPreview,
@@ -3977,6 +4032,8 @@ export {
3977
4032
  formatCurrency,
3978
4033
  formatDate3 as formatDate,
3979
4034
  formatInterval,
3980
- isStripeConfigured
4035
+ isStripeConfigured,
4036
+ useBillingContext,
4037
+ useOptionalBillingContext
3981
4038
  };
3982
4039
  //# sourceMappingURL=index.mjs.map