@burdenoff/microfe-billing 2026.625.3 → 2026.625.5

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 (98) hide show
  1. package/dist/billing/lib/native-purchases.js +2 -44
  2. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +192 -187
  3. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
  4. package/dist/billing/modules/addons/pages/AddonCreatePage.js +322 -317
  5. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  6. package/dist/billing/modules/addons/pages/AddonDetailPage.js +190 -185
  7. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  8. package/dist/billing/modules/addons/pages/AddonEditPage.js +297 -292
  9. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  10. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +60 -75
  11. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
  12. package/dist/billing/modules/addons/pages/AddonsListPage.js +86 -101
  13. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  14. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +124 -121
  15. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
  16. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +103 -111
  17. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  18. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +196 -160
  19. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  20. package/dist/billing/modules/billing/pages/InvoicesListPage.js +58 -73
  21. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  22. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +65 -75
  23. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
  24. package/dist/billing/modules/billing/pages/RefundsPage.js +399 -399
  25. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  26. package/dist/billing/modules/billing/pages/TransactionsPage.js +49 -48
  27. package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
  28. package/dist/billing/modules/billing/pages/UserRefundsPage.js +144 -151
  29. package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -1
  30. package/dist/billing/modules/checkout/pages/CheckoutPage.js +430 -425
  31. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  32. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +121 -93
  33. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  34. package/dist/billing/modules/coupons/pages/CouponsListPage.js +154 -152
  35. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  36. package/dist/billing/modules/coupons/pages/CreateCouponPage.js +467 -462
  37. package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
  38. package/dist/billing/modules/coupons/pages/EditCouponPage.js +294 -286
  39. package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
  40. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +123 -117
  41. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  42. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +43 -42
  43. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  44. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +192 -207
  45. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  46. package/dist/billing/modules/credits/pages/CreditsPage.js +40 -56
  47. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  48. package/dist/billing/modules/dashboard/pages/OverviewPage.js +128 -121
  49. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  50. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +165 -180
  51. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  52. package/dist/billing/modules/earnings/pages/EarningsPage.js +103 -100
  53. package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
  54. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +175 -175
  55. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  56. package/dist/billing/modules/earnings/pages/PayoutsPage.js +96 -96
  57. package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
  58. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +42 -40
  59. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
  60. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +45 -38
  61. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  62. package/dist/billing/modules/plans/pages/PlanCreatePage.js +339 -334
  63. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  64. package/dist/billing/modules/plans/pages/PlanDetailPage.js +80 -74
  65. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  66. package/dist/billing/modules/plans/pages/PlanEditPage.js +342 -337
  67. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  68. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +38 -53
  69. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  70. package/dist/billing/modules/plans/pages/PlansListPage.js +60 -75
  71. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  72. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +242 -237
  73. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
  74. package/dist/billing/modules/promotions/pages/PromotionsListPage.js +29 -39
  75. package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -1
  76. package/dist/billing/modules/quota/pages/QuotaPage.js +1 -0
  77. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +299 -294
  78. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  79. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +191 -186
  80. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  81. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +308 -303
  82. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  83. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +57 -78
  84. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  85. package/dist/billing/modules/settings/pages/SettingsPage.js +79 -78
  86. package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
  87. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +15 -13
  88. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
  89. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +338 -299
  90. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  91. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +82 -103
  92. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  93. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +59 -54
  94. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  95. package/dist/billing/modules/usage/pages/UsagePage.js +172 -215
  96. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  97. package/package.json +2 -2
  98. package/dist/billing/lib/native-purchases.js.map +0 -1
@@ -7,287 +7,292 @@ import { useBillingNavigate as i } from "../../../hooks/useBillingNavigate.js";
7
7
  import { useState as a } from "react";
8
8
  import { ArrowLeft as o, Gift as s, Info as c, Save as l } from "lucide-react";
9
9
  import { jsx as u, jsxs as d } from "react/jsx-runtime";
10
+ import { PagePurpose as f } from "@burdenoff/fe-libs/ui";
10
11
  //#region src/billing/modules/promotions/pages/CreatePromotionPage.tsx
11
- var f = [
12
+ var p = [
12
13
  "vibecontrols",
13
14
  "workspaces",
14
15
  "botlit",
15
16
  "fluidgrids",
16
17
  "healthybowl"
17
- ], p = () => {
18
- let p = i(), m = n(), [h] = r({ refetchQueries: ["ListPromotions"] }), [g, _] = a(!1), [v, y] = a({}), b = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], [x, S] = a({
18
+ ], m = () => {
19
+ let m = i(), h = n(), [g] = r({ refetchQueries: ["ListPromotions"] }), [_, v] = a(!1), [y, b] = a({}), x = (/* @__PURE__ */ new Date()).toISOString().split("T")[0], [S, C] = a({
19
20
  name: "",
20
21
  description: "",
21
- startsAt: b,
22
+ startsAt: x,
22
23
  expiresAt: "",
23
24
  bonusMonths: 1,
24
25
  maxRedemptions: "",
25
26
  applicableProductIds: [],
26
27
  applicablePlanIds: ""
27
28
  });
28
- if (!m.canManagePlans) return /* @__PURE__ */ u(e, { message: "You don't have permission to create promotions." });
29
- let C = (e, t) => S((n) => ({
29
+ if (!h.canManagePlans) return /* @__PURE__ */ u(e, { message: "You don't have permission to create promotions." });
30
+ let w = (e, t) => C((n) => ({
30
31
  ...n,
31
32
  [e]: t
32
- })), w = (e) => {
33
- C("applicableProductIds", x.applicableProductIds.includes(e) ? x.applicableProductIds.filter((t) => t !== e) : [...x.applicableProductIds, e]);
34
- }, T = () => {
33
+ })), T = (e) => {
34
+ w("applicableProductIds", S.applicableProductIds.includes(e) ? S.applicableProductIds.filter((t) => t !== e) : [...S.applicableProductIds, e]);
35
+ }, E = () => {
35
36
  let e = {};
36
- return x.name.trim() || (e.name = "Name is required"), x.startsAt || (e.startsAt = "Start date is required"), x.expiresAt || (e.expiresAt = "End date is required"), x.expiresAt && x.expiresAt <= x.startsAt && (e.expiresAt = "End date must be after start date"), x.bonusMonths < 1 && (e.bonusMonths = "Must be at least 1"), y(e), Object.keys(e).length === 0;
37
+ return S.name.trim() || (e.name = "Name is required"), S.startsAt || (e.startsAt = "Start date is required"), S.expiresAt || (e.expiresAt = "End date is required"), S.expiresAt && S.expiresAt <= S.startsAt && (e.expiresAt = "End date must be after start date"), S.bonusMonths < 1 && (e.bonusMonths = "Must be at least 1"), b(e), Object.keys(e).length === 0;
37
38
  };
38
39
  return /* @__PURE__ */ d("div", {
39
40
  className: "max-w-2xl mx-auto p-4 sm:p-6 space-y-6",
40
- children: [/* @__PURE__ */ d("div", {
41
- className: "flex items-center gap-4",
42
- children: [/* @__PURE__ */ u("button", {
43
- type: "button",
44
- onClick: () => p("/promotions"),
45
- "aria-label": "Back to promotions",
46
- className: "p-2 rounded-button hover:bg-bg-sunken text-text-muted hover:text-text-primary transition-colors",
47
- children: /* @__PURE__ */ u(o, { className: "size-5" })
48
- }), /* @__PURE__ */ u(t, {
49
- title: "Create Promotion",
50
- description: "Offer bonus free renewal months to subscribers who sign up within the promotion window",
51
- icon: /* @__PURE__ */ u(s, { className: "size-6" })
52
- })]
53
- }), /* @__PURE__ */ d("form", {
54
- onSubmit: async (e) => {
55
- if (e.preventDefault(), T()) {
56
- _(!0);
57
- try {
58
- let e = x.applicablePlanIds.split(",").flatMap((e) => {
59
- let t = e.trim();
60
- return t ? [t] : [];
61
- });
62
- await h({ variables: { input: {
63
- name: x.name.trim(),
64
- description: x.description.trim() || void 0,
65
- startsAt: new Date(x.startsAt).toISOString(),
66
- expiresAt: new Date(x.expiresAt).toISOString(),
67
- bonusMonths: x.bonusMonths,
68
- maxRedemptions: x.maxRedemptions ? parseInt(x.maxRedemptions) : void 0,
69
- applicableProductIds: x.applicableProductIds,
70
- applicablePlanIds: e
71
- } } }), p("/promotions");
72
- } catch (e) {
73
- y({ name: e instanceof Error ? e.message : "Failed to create promotion" });
74
- } finally {
75
- _(!1);
41
+ children: [
42
+ /* @__PURE__ */ d("div", {
43
+ className: "flex items-center gap-4",
44
+ children: [/* @__PURE__ */ u("button", {
45
+ type: "button",
46
+ onClick: () => m("/promotions"),
47
+ "aria-label": "Back to promotions",
48
+ className: "p-2 rounded-button hover:bg-bg-sunken text-text-muted hover:text-text-primary transition-colors",
49
+ children: /* @__PURE__ */ u(o, { className: "size-5" })
50
+ }), /* @__PURE__ */ u(t, {
51
+ title: "Create Promotion",
52
+ description: "Offer bonus free renewal months to subscribers who sign up within the promotion window",
53
+ icon: /* @__PURE__ */ u(s, { className: "size-6" })
54
+ })]
55
+ }),
56
+ /* @__PURE__ */ u(f, { children: "Set up a time-bounded campaign that rewards new subscribers with bonus free renewal months. Define the bonus, the window during which it applies, an optional redemption cap and which products it covers — then activate it to start offering it." }),
57
+ /* @__PURE__ */ d("form", {
58
+ onSubmit: async (e) => {
59
+ if (e.preventDefault(), E()) {
60
+ v(!0);
61
+ try {
62
+ let e = S.applicablePlanIds.split(",").flatMap((e) => {
63
+ let t = e.trim();
64
+ return t ? [t] : [];
65
+ });
66
+ await g({ variables: { input: {
67
+ name: S.name.trim(),
68
+ description: S.description.trim() || void 0,
69
+ startsAt: new Date(S.startsAt).toISOString(),
70
+ expiresAt: new Date(S.expiresAt).toISOString(),
71
+ bonusMonths: S.bonusMonths,
72
+ maxRedemptions: S.maxRedemptions ? parseInt(S.maxRedemptions) : void 0,
73
+ applicableProductIds: S.applicableProductIds,
74
+ applicablePlanIds: e
75
+ } } }), m("/promotions");
76
+ } catch (e) {
77
+ b({ name: e instanceof Error ? e.message : "Failed to create promotion" });
78
+ } finally {
79
+ v(!1);
80
+ }
76
81
  }
77
- }
78
- },
79
- className: "space-y-5",
80
- children: [
81
- /* @__PURE__ */ d("div", {
82
- className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
83
- children: [
84
- /* @__PURE__ */ u("h3", {
85
- className: "font-semibold text-text-primary",
86
- children: "Promotion Details"
87
- }),
88
- /* @__PURE__ */ d("div", { children: [
89
- /* @__PURE__ */ u("label", {
90
- className: "block text-sm font-medium text-text-primary mb-1",
91
- children: "Name *"
92
- }),
93
- /* @__PURE__ */ u("input", {
94
- type: "text",
95
- value: x.name,
96
- onChange: (e) => C("name", e.target.value),
97
- placeholder: "e.g. June Launch Offer",
98
- className: `w-full px-3 py-2 rounded-input border ${v.name ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
99
- }),
100
- v.name && /* @__PURE__ */ u("p", {
101
- className: "text-xs text-status-error-text mt-1",
102
- children: v.name
103
- })
104
- ] }),
105
- /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
106
- className: "block text-sm font-medium text-text-primary mb-1",
107
- children: "Description"
108
- }), /* @__PURE__ */ u("textarea", {
109
- value: x.description,
110
- onChange: (e) => C("description", e.target.value),
111
- placeholder: "Subscribe in June and get 2 extra months free!",
112
- rows: 2,
113
- className: "w-full px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
114
- })] })
115
- ]
116
- }),
117
- /* @__PURE__ */ d("div", {
118
- className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
119
- children: [
120
- /* @__PURE__ */ u("h3", {
121
- className: "font-semibold text-text-primary",
122
- children: "Bonus Configuration"
123
- }),
124
- /* @__PURE__ */ d("div", { children: [
125
- /* @__PURE__ */ u("label", {
126
- className: "block text-sm font-medium text-text-primary mb-1",
127
- children: "Bonus Months *"
128
- }),
129
- /* @__PURE__ */ u("input", {
130
- type: "number",
131
- value: x.bonusMonths,
132
- min: 1,
133
- max: 12,
134
- onChange: (e) => C("bonusMonths", parseInt(e.target.value) || 1),
135
- className: `w-32 px-3 py-2 rounded-input border ${v.bonusMonths ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
82
+ },
83
+ className: "space-y-5",
84
+ children: [
85
+ /* @__PURE__ */ d("div", {
86
+ className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
87
+ children: [
88
+ /* @__PURE__ */ u("h3", {
89
+ className: "font-semibold text-text-primary",
90
+ children: "Promotion Details"
136
91
  }),
137
- v.bonusMonths && /* @__PURE__ */ u("p", {
138
- className: "text-xs text-status-error-text mt-1",
139
- children: v.bonusMonths
140
- }),
141
- /* @__PURE__ */ d("div", {
142
- className: "mt-2 flex items-start gap-2 p-3 bg-[var(--color-accent-soft)] rounded-lg text-sm text-text-muted",
143
- children: [/* @__PURE__ */ u(c, { className: "size-4 shrink-0 mt-0.5 text-text-link" }), /* @__PURE__ */ d("span", { children: [
144
- "Users who subscribe during this window get",
145
- " ",
146
- /* @__PURE__ */ d("strong", {
147
- className: "text-text-primary",
148
- children: [
149
- x.bonusMonths,
150
- " free renewal",
151
- x.bonusMonths === 1 ? "" : "s"
152
- ]
153
- }),
154
- " ",
155
- "after their first paid period — their quota resets each month as normal."
156
- ] })]
157
- })
158
- ] }),
159
- /* @__PURE__ */ d("div", { children: [
160
- /* @__PURE__ */ u("label", {
92
+ /* @__PURE__ */ d("div", { children: [
93
+ /* @__PURE__ */ u("label", {
94
+ className: "block text-sm font-medium text-text-primary mb-1",
95
+ children: "Name *"
96
+ }),
97
+ /* @__PURE__ */ u("input", {
98
+ type: "text",
99
+ value: S.name,
100
+ onChange: (e) => w("name", e.target.value),
101
+ placeholder: "e.g. June Launch Offer",
102
+ className: `w-full px-3 py-2 rounded-input border ${y.name ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
103
+ }),
104
+ y.name && /* @__PURE__ */ u("p", {
105
+ className: "text-xs text-status-error-text mt-1",
106
+ children: y.name
107
+ })
108
+ ] }),
109
+ /* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("label", {
161
110
  className: "block text-sm font-medium text-text-primary mb-1",
162
- children: "Max Redemptions"
163
- }),
164
- /* @__PURE__ */ u("input", {
165
- type: "number",
166
- value: x.maxRedemptions,
167
- min: 1,
168
- onChange: (e) => C("maxRedemptions", e.target.value),
169
- placeholder: "Unlimited",
170
- className: "w-48 px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
111
+ children: "Description"
112
+ }), /* @__PURE__ */ u("textarea", {
113
+ value: S.description,
114
+ onChange: (e) => w("description", e.target.value),
115
+ placeholder: "Subscribe in June and get 2 extra months free!",
116
+ rows: 2,
117
+ className: "w-full px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
118
+ })] })
119
+ ]
120
+ }),
121
+ /* @__PURE__ */ d("div", {
122
+ className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
123
+ children: [
124
+ /* @__PURE__ */ u("h3", {
125
+ className: "font-semibold text-text-primary",
126
+ children: "Bonus Configuration"
171
127
  }),
172
- /* @__PURE__ */ u("p", {
173
- className: "text-xs text-text-muted mt-1",
174
- children: "Leave empty for no cap"
175
- })
176
- ] })
177
- ]
178
- }),
179
- /* @__PURE__ */ d("div", {
180
- className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
181
- children: [
182
- /* @__PURE__ */ u("h3", {
183
- className: "font-semibold text-text-primary",
184
- children: "Active Window"
185
- }),
186
- /* @__PURE__ */ d("div", {
187
- className: "grid grid-cols-2 gap-4",
188
- children: [/* @__PURE__ */ d("div", { children: [
128
+ /* @__PURE__ */ d("div", { children: [
189
129
  /* @__PURE__ */ u("label", {
190
130
  className: "block text-sm font-medium text-text-primary mb-1",
191
- children: "Start Date *"
131
+ children: "Bonus Months *"
192
132
  }),
193
133
  /* @__PURE__ */ u("input", {
194
- type: "date",
195
- value: x.startsAt,
196
- onChange: (e) => C("startsAt", e.target.value),
197
- className: `w-full px-3 py-2 rounded-input border ${v.startsAt ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
134
+ type: "number",
135
+ value: S.bonusMonths,
136
+ min: 1,
137
+ max: 12,
138
+ onChange: (e) => w("bonusMonths", parseInt(e.target.value) || 1),
139
+ className: `w-32 px-3 py-2 rounded-input border ${y.bonusMonths ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
198
140
  }),
199
- v.startsAt && /* @__PURE__ */ u("p", {
141
+ y.bonusMonths && /* @__PURE__ */ u("p", {
200
142
  className: "text-xs text-status-error-text mt-1",
201
- children: v.startsAt
143
+ children: y.bonusMonths
144
+ }),
145
+ /* @__PURE__ */ d("div", {
146
+ className: "mt-2 flex items-start gap-2 p-3 bg-[var(--color-accent-soft)] rounded-lg text-sm text-text-muted",
147
+ children: [/* @__PURE__ */ u(c, { className: "size-4 shrink-0 mt-0.5 text-text-link" }), /* @__PURE__ */ d("span", { children: [
148
+ "Users who subscribe during this window get",
149
+ " ",
150
+ /* @__PURE__ */ d("strong", {
151
+ className: "text-text-primary",
152
+ children: [
153
+ S.bonusMonths,
154
+ " free renewal",
155
+ S.bonusMonths === 1 ? "" : "s"
156
+ ]
157
+ }),
158
+ " ",
159
+ "after their first paid period — their quota resets each month as normal."
160
+ ] })]
202
161
  })
203
- ] }), /* @__PURE__ */ d("div", { children: [
162
+ ] }),
163
+ /* @__PURE__ */ d("div", { children: [
204
164
  /* @__PURE__ */ u("label", {
205
165
  className: "block text-sm font-medium text-text-primary mb-1",
206
- children: "End Date *"
166
+ children: "Max Redemptions"
207
167
  }),
208
168
  /* @__PURE__ */ u("input", {
209
- type: "date",
210
- value: x.expiresAt,
211
- onChange: (e) => C("expiresAt", e.target.value),
212
- min: x.startsAt,
213
- className: `w-full px-3 py-2 rounded-input border ${v.expiresAt ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
169
+ type: "number",
170
+ value: S.maxRedemptions,
171
+ min: 1,
172
+ onChange: (e) => w("maxRedemptions", e.target.value),
173
+ placeholder: "Unlimited",
174
+ className: "w-48 px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary placeholder:text-text-muted focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
214
175
  }),
215
- v.expiresAt && /* @__PURE__ */ u("p", {
216
- className: "text-xs text-status-error-text mt-1",
217
- children: v.expiresAt
176
+ /* @__PURE__ */ u("p", {
177
+ className: "text-xs text-text-muted mt-1",
178
+ children: "Leave empty for no cap"
218
179
  })
219
- ] })]
220
- }),
221
- /* @__PURE__ */ u("p", {
222
- className: "text-xs text-text-muted",
223
- children: "Only purchases made between these dates will receive the bonus months"
224
- })
225
- ]
226
- }),
227
- /* @__PURE__ */ d("div", {
228
- className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
229
- children: [
230
- /* @__PURE__ */ u("h3", {
231
- className: "font-semibold text-text-primary",
232
- children: "Scope"
233
- }),
234
- /* @__PURE__ */ d("div", { children: [
235
- /* @__PURE__ */ u("label", {
236
- className: "block text-sm font-medium text-text-primary mb-2",
237
- children: "Applicable Products"
180
+ ] })
181
+ ]
182
+ }),
183
+ /* @__PURE__ */ d("div", {
184
+ className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
185
+ children: [
186
+ /* @__PURE__ */ u("h3", {
187
+ className: "font-semibold text-text-primary",
188
+ children: "Active Window"
238
189
  }),
239
- /* @__PURE__ */ u("div", {
240
- className: "flex flex-wrap gap-2",
241
- children: f.map((e) => /* @__PURE__ */ u("button", {
242
- type: "button",
243
- onClick: () => w(e),
244
- className: `px-3 py-1.5 rounded-lg border text-sm transition-colors ${x.applicableProductIds.includes(e) ? "border-action-primary-bg bg-[var(--color-accent-soft)] text-text-link font-medium" : "border-border-subtle hover:border-action-primary-bg/50"}`,
245
- children: e
246
- }, e))
190
+ /* @__PURE__ */ d("div", {
191
+ className: "grid grid-cols-2 gap-4",
192
+ children: [/* @__PURE__ */ d("div", { children: [
193
+ /* @__PURE__ */ u("label", {
194
+ className: "block text-sm font-medium text-text-primary mb-1",
195
+ children: "Start Date *"
196
+ }),
197
+ /* @__PURE__ */ u("input", {
198
+ type: "date",
199
+ value: S.startsAt,
200
+ onChange: (e) => w("startsAt", e.target.value),
201
+ className: `w-full px-3 py-2 rounded-input border ${y.startsAt ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
202
+ }),
203
+ y.startsAt && /* @__PURE__ */ u("p", {
204
+ className: "text-xs text-status-error-text mt-1",
205
+ children: y.startsAt
206
+ })
207
+ ] }), /* @__PURE__ */ d("div", { children: [
208
+ /* @__PURE__ */ u("label", {
209
+ className: "block text-sm font-medium text-text-primary mb-1",
210
+ children: "End Date *"
211
+ }),
212
+ /* @__PURE__ */ u("input", {
213
+ type: "date",
214
+ value: S.expiresAt,
215
+ onChange: (e) => w("expiresAt", e.target.value),
216
+ min: S.startsAt,
217
+ className: `w-full px-3 py-2 rounded-input border ${y.expiresAt ? "border-status-error-border" : "border-border-subtle"} bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]`
218
+ }),
219
+ y.expiresAt && /* @__PURE__ */ u("p", {
220
+ className: "text-xs text-status-error-text mt-1",
221
+ children: y.expiresAt
222
+ })
223
+ ] })]
247
224
  }),
248
225
  /* @__PURE__ */ u("p", {
249
- className: "text-xs text-text-muted mt-1",
250
- children: x.applicableProductIds.length === 0 ? "No selection = applies to all products" : `Applies to: ${x.applicableProductIds.join(", ")}`
226
+ className: "text-xs text-text-muted",
227
+ children: "Only purchases made between these dates will receive the bonus months"
251
228
  })
252
- ] }),
253
- /* @__PURE__ */ d("div", { children: [
254
- /* @__PURE__ */ u("label", {
255
- className: "block text-sm font-medium text-text-primary mb-1",
256
- children: "Plan IDs (optional)"
257
- }),
258
- /* @__PURE__ */ u("input", {
259
- type: "text",
260
- value: x.applicablePlanIds,
261
- onChange: (e) => C("applicablePlanIds", e.target.value),
262
- placeholder: "plan-vibecontrols-pro-monthly, plan-vibecontrols-pro-yearly",
263
- className: "w-full px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary placeholder:text-text-muted text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
229
+ ]
230
+ }),
231
+ /* @__PURE__ */ d("div", {
232
+ className: "bg-bg-surface border border-border-seam rounded-card p-5 space-y-4 shadow-[var(--shadow-elevation-1)]",
233
+ children: [
234
+ /* @__PURE__ */ u("h3", {
235
+ className: "font-semibold text-text-primary",
236
+ children: "Scope"
264
237
  }),
265
- /* @__PURE__ */ u("p", {
266
- className: "text-xs text-text-muted mt-1",
267
- children: "Comma-separated. Leave empty to apply to all plans"
268
- })
269
- ] })
270
- ]
271
- }),
272
- /* @__PURE__ */ d("div", {
273
- className: "flex gap-3 justify-end",
274
- children: [/* @__PURE__ */ u("button", {
275
- type: "button",
276
- onClick: () => p("/promotions"),
277
- className: "px-5 py-2 rounded-button border border-border-subtle text-text-primary hover:bg-bg-sunken text-sm font-medium transition-colors",
278
- children: "Cancel"
279
- }), /* @__PURE__ */ d("button", {
280
- type: "submit",
281
- disabled: g,
282
- className: "px-5 py-2 rounded-button bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bgHover flex items-center gap-2 text-sm font-medium transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:opacity-50",
283
- children: [g ? /* @__PURE__ */ u("div", { className: "size-4 border-2 border-action-primary-text border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ u(l, { className: "size-4" }), "Create Promotion"]
284
- })]
285
- })
286
- ]
287
- })]
238
+ /* @__PURE__ */ d("div", { children: [
239
+ /* @__PURE__ */ u("label", {
240
+ className: "block text-sm font-medium text-text-primary mb-2",
241
+ children: "Applicable Products"
242
+ }),
243
+ /* @__PURE__ */ u("div", {
244
+ className: "flex flex-wrap gap-2",
245
+ children: p.map((e) => /* @__PURE__ */ u("button", {
246
+ type: "button",
247
+ onClick: () => T(e),
248
+ className: `px-3 py-1.5 rounded-lg border text-sm transition-colors ${S.applicableProductIds.includes(e) ? "border-action-primary-bg bg-[var(--color-accent-soft)] text-text-link font-medium" : "border-border-subtle hover:border-action-primary-bg/50"}`,
249
+ children: e
250
+ }, e))
251
+ }),
252
+ /* @__PURE__ */ u("p", {
253
+ className: "text-xs text-text-muted mt-1",
254
+ children: S.applicableProductIds.length === 0 ? "No selection = applies to all products" : `Applies to: ${S.applicableProductIds.join(", ")}`
255
+ })
256
+ ] }),
257
+ /* @__PURE__ */ d("div", { children: [
258
+ /* @__PURE__ */ u("label", {
259
+ className: "block text-sm font-medium text-text-primary mb-1",
260
+ children: "Plan IDs (optional)"
261
+ }),
262
+ /* @__PURE__ */ u("input", {
263
+ type: "text",
264
+ value: S.applicablePlanIds,
265
+ onChange: (e) => w("applicablePlanIds", e.target.value),
266
+ placeholder: "plan-vibecontrols-pro-monthly, plan-vibecontrols-pro-yearly",
267
+ className: "w-full px-3 py-2 rounded-input border border-border-subtle bg-bg-surface text-text-primary placeholder:text-text-muted text-sm focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
268
+ }),
269
+ /* @__PURE__ */ u("p", {
270
+ className: "text-xs text-text-muted mt-1",
271
+ children: "Comma-separated. Leave empty to apply to all plans"
272
+ })
273
+ ] })
274
+ ]
275
+ }),
276
+ /* @__PURE__ */ d("div", {
277
+ className: "flex gap-3 justify-end",
278
+ children: [/* @__PURE__ */ u("button", {
279
+ type: "button",
280
+ onClick: () => m("/promotions"),
281
+ className: "px-5 py-2 rounded-button border border-border-subtle text-text-primary hover:bg-bg-sunken text-sm font-medium transition-colors",
282
+ children: "Cancel"
283
+ }), /* @__PURE__ */ d("button", {
284
+ type: "submit",
285
+ disabled: _,
286
+ className: "px-5 py-2 rounded-button bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bgHover flex items-center gap-2 text-sm font-medium transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:opacity-50",
287
+ children: [_ ? /* @__PURE__ */ u("div", { className: "size-4 border-2 border-action-primary-text border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ u(l, { className: "size-4" }), "Create Promotion"]
288
+ })]
289
+ })
290
+ ]
291
+ })
292
+ ]
288
293
  });
289
294
  };
290
295
  //#endregion
291
- export { p as CreatePromotionPage };
296
+ export { m as CreatePromotionPage };
292
297
 
293
298
  //# sourceMappingURL=CreatePromotionPage.js.map