@burdenoff/microfe-billing 2026.614.1 → 2026.623.2
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.
- package/dist/billing/BillingAdminRoutes.js +7 -6
- package/dist/billing/BillingAdminRoutes.js.map +1 -1
- package/dist/billing/BillingRoot.js +1 -1
- package/dist/billing/BillingRoot.js.map +1 -1
- package/dist/billing/modules/addons/components/FloatingCartDrawer.js +22 -22
- package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonCreatePage.js +31 -31
- package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonDetailPage.js +39 -39
- package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonEditPage.js +29 -29
- package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js +91 -91
- package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
- package/dist/billing/modules/analytics/pages/AnalyticsPage.js +40 -40
- package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +115 -115
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoicesListPage.js +75 -72
- package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/RefundsPage.js +126 -126
- package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/UserRefundsPage.js +45 -45
- package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -1
- package/dist/billing/modules/checkout/components/BillingAccountSelector.js +25 -25
- package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
- package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js +31 -35
- package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js.map +1 -1
- package/dist/billing/modules/checkout/components/CreditsAmountInput.js +9 -9
- package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
- package/dist/billing/modules/checkout/components/OrderSummary.js +31 -31
- package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
- package/dist/billing/modules/checkout/components/PromoCodeInput.js +8 -8
- package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
- package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
- package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
- package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +9 -9
- package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
- package/dist/billing/modules/checkout/components/StripePaymentForm.js +21 -21
- package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
- package/dist/billing/modules/checkout/components/SubscriptionSelector.js +11 -11
- package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
- package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +31 -31
- package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
- package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js +23 -23
- package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +91 -91
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js +62 -62
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CouponsListPage.js +72 -60
- package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +66 -66
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/EditCouponPage.js +46 -46
- package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/AdminCreditsPage.js +19 -19
- package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +37 -37
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +90 -90
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditsPage.js +41 -41
- package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
- package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +31 -31
- package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +35 -35
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
- package/dist/billing/modules/dashboard/components/BillingAccountCard.js +24 -24
- package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
- package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +99 -99
- package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
- package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +23 -23
- package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +22 -22
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
- package/dist/billing/modules/dashboard/pages/OverviewPage.js +58 -58
- package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js +126 -126
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +83 -79
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +16 -16
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +40 -40
- package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanCreatePage.js +35 -35
- package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanDetailPage.js +57 -57
- package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanEditPage.js +35 -35
- package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js +57 -57
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js +52 -52
- package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +40 -39
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
- package/dist/billing/modules/promotions/pages/PromotionsListPage.js +22 -19
- package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +34 -34
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +47 -47
- package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +39 -39
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +52 -52
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +23 -23
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +259 -246
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +88 -85
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +51 -51
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js +206 -196
- package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
- package/dist/billing/shared/components/ServerError.js +4 -4
- package/dist/billing/shared/components/ServerError.js.map +1 -1
- package/dist/billing/shared/components/StatCard.js +11 -33
- package/dist/billing/shared/components/StatCard.js.map +1 -1
- package/dist/billing/shared/ui/Card.js +15 -0
- package/dist/billing/shared/ui/Card.js.map +1 -0
- package/dist/billing/shared/ui/MetricCard.js +44 -0
- package/dist/billing/shared/ui/MetricCard.js.map +1 -0
- package/dist/billing/shared/ui/ProgressBar.js +30 -0
- package/dist/billing/shared/ui/ProgressBar.js.map +1 -0
- package/dist/billing/shared/ui/SectionHeader.js +2 -0
- package/dist/billing/shared/ui/StatusPill.js +28 -0
- package/dist/billing/shared/ui/StatusPill.js.map +1 -0
- package/dist/billing/shared/ui/index.js +5 -0
- package/dist/billing/shared/utils/tokens.js +13 -30
- package/dist/billing/shared/utils/tokens.js.map +1 -1
- package/package.json +1 -1
|
@@ -72,11 +72,11 @@ var d = () => {
|
|
|
72
72
|
})
|
|
73
73
|
}),
|
|
74
74
|
/* @__PURE__ */ l("div", {
|
|
75
|
-
className: "border border-border rounded-
|
|
75
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
76
76
|
children: [/* @__PURE__ */ c("div", {
|
|
77
|
-
className: "p-4 border-b border-border bg-
|
|
77
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
78
78
|
children: /* @__PURE__ */ c("h2", {
|
|
79
|
-
className: "font-semibold text-
|
|
79
|
+
className: "font-semibold text-text-primary",
|
|
80
80
|
children: "Basic Information"
|
|
81
81
|
})
|
|
82
82
|
}), /* @__PURE__ */ l("div", {
|
|
@@ -85,7 +85,7 @@ var d = () => {
|
|
|
85
85
|
/* @__PURE__ */ l("div", { children: [
|
|
86
86
|
/* @__PURE__ */ c("label", {
|
|
87
87
|
htmlFor: "name",
|
|
88
|
-
className: "block text-sm font-medium text-
|
|
88
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
89
89
|
children: "Quota Key *"
|
|
90
90
|
}),
|
|
91
91
|
/* @__PURE__ */ c("input", {
|
|
@@ -93,12 +93,12 @@ var d = () => {
|
|
|
93
93
|
type: "text",
|
|
94
94
|
value: _,
|
|
95
95
|
onChange: (e) => v(e.target.value),
|
|
96
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
96
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono text-sm",
|
|
97
97
|
placeholder: "e.g., sessions-started, tunnels-created",
|
|
98
98
|
required: !0
|
|
99
99
|
}),
|
|
100
100
|
/* @__PURE__ */ l("p", {
|
|
101
|
-
className: "text-xs text-muted
|
|
101
|
+
className: "text-xs text-text-muted mt-1",
|
|
102
102
|
children: [
|
|
103
103
|
"Internal machine key, must match the ",
|
|
104
104
|
/* @__PURE__ */ c("code", { children: "quotaName" }),
|
|
@@ -112,7 +112,7 @@ var d = () => {
|
|
|
112
112
|
/* @__PURE__ */ l("div", { children: [
|
|
113
113
|
/* @__PURE__ */ c("label", {
|
|
114
114
|
htmlFor: "displayName",
|
|
115
|
-
className: "block text-sm font-medium text-
|
|
115
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
116
116
|
children: "Display Name *"
|
|
117
117
|
}),
|
|
118
118
|
/* @__PURE__ */ c("input", {
|
|
@@ -120,19 +120,19 @@ var d = () => {
|
|
|
120
120
|
type: "text",
|
|
121
121
|
value: y,
|
|
122
122
|
onChange: (e) => b(e.target.value),
|
|
123
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
123
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
124
124
|
placeholder: "e.g., Tunnels, Session Starts, Webhooks",
|
|
125
125
|
required: !0
|
|
126
126
|
}),
|
|
127
127
|
/* @__PURE__ */ c("p", {
|
|
128
|
-
className: "text-xs text-muted
|
|
128
|
+
className: "text-xs text-text-muted mt-1",
|
|
129
129
|
children: "Human-readable name shown to users in billing and usage UI."
|
|
130
130
|
})
|
|
131
131
|
] }),
|
|
132
132
|
/* @__PURE__ */ l("div", { children: [
|
|
133
133
|
/* @__PURE__ */ c("label", {
|
|
134
134
|
htmlFor: "description",
|
|
135
|
-
className: "block text-sm font-medium text-
|
|
135
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
136
136
|
children: "Description"
|
|
137
137
|
}),
|
|
138
138
|
/* @__PURE__ */ c("textarea", {
|
|
@@ -140,25 +140,25 @@ var d = () => {
|
|
|
140
140
|
value: x,
|
|
141
141
|
onChange: (e) => S(e.target.value),
|
|
142
142
|
rows: 2,
|
|
143
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
143
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none",
|
|
144
144
|
placeholder: "e.g., Active tunnels created through VibeControls (slot freed on delete)"
|
|
145
145
|
}),
|
|
146
146
|
/* @__PURE__ */ c("p", {
|
|
147
|
-
className: "text-xs text-muted
|
|
147
|
+
className: "text-xs text-text-muted mt-1",
|
|
148
148
|
children: "Short explanation shown in billing and usage detail views."
|
|
149
149
|
})
|
|
150
150
|
] }),
|
|
151
151
|
/* @__PURE__ */ l("div", { children: [
|
|
152
152
|
/* @__PURE__ */ c("label", {
|
|
153
153
|
htmlFor: "quotaType",
|
|
154
|
-
className: "block text-sm font-medium text-
|
|
154
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
155
155
|
children: "Quota Type *"
|
|
156
156
|
}),
|
|
157
157
|
/* @__PURE__ */ l("select", {
|
|
158
158
|
id: "quotaType",
|
|
159
159
|
value: k,
|
|
160
160
|
onChange: (e) => A(e.target.value),
|
|
161
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
161
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
162
162
|
children: [/* @__PURE__ */ c("option", {
|
|
163
163
|
value: r.PRODUCT_SPECIFIC,
|
|
164
164
|
children: "Product Specific"
|
|
@@ -168,7 +168,7 @@ var d = () => {
|
|
|
168
168
|
})]
|
|
169
169
|
}),
|
|
170
170
|
/* @__PURE__ */ c("p", {
|
|
171
|
-
className: "text-xs text-muted
|
|
171
|
+
className: "text-xs text-text-muted mt-1",
|
|
172
172
|
children: k === r.POOLED ? "Shared across all products" : "Specific to individual products"
|
|
173
173
|
})
|
|
174
174
|
] }),
|
|
@@ -179,27 +179,27 @@ var d = () => {
|
|
|
179
179
|
type: "checkbox",
|
|
180
180
|
checked: j,
|
|
181
181
|
onChange: (e) => M(e.target.checked),
|
|
182
|
-
className: "size-4 rounded border-border text-
|
|
182
|
+
className: "size-4 rounded border-border-subtle text-text-link focus:ring-[var(--color-focus-ring)]"
|
|
183
183
|
}), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
|
|
184
184
|
htmlFor: "reusable",
|
|
185
|
-
className: "text-sm font-medium text-
|
|
185
|
+
className: "text-sm font-medium text-text-primary",
|
|
186
186
|
children: "Reusable Quota"
|
|
187
187
|
}), /* @__PURE__ */ c("p", {
|
|
188
|
-
className: "text-xs text-muted
|
|
188
|
+
className: "text-xs text-text-muted",
|
|
189
189
|
children: "Enable for quotas like seats or bots that can be freed up"
|
|
190
190
|
})] })]
|
|
191
191
|
}),
|
|
192
192
|
/* @__PURE__ */ l("div", { children: [
|
|
193
193
|
/* @__PURE__ */ c("label", {
|
|
194
194
|
htmlFor: "resetPeriod",
|
|
195
|
-
className: "block text-sm font-medium text-
|
|
195
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
196
196
|
children: "Reset Period"
|
|
197
197
|
}),
|
|
198
198
|
/* @__PURE__ */ l("select", {
|
|
199
199
|
id: "resetPeriod",
|
|
200
200
|
value: N,
|
|
201
201
|
onChange: (e) => P(e.target.value),
|
|
202
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
202
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
203
203
|
children: [
|
|
204
204
|
/* @__PURE__ */ c("option", {
|
|
205
205
|
value: n.NEVER,
|
|
@@ -216,7 +216,7 @@ var d = () => {
|
|
|
216
216
|
]
|
|
217
217
|
}),
|
|
218
218
|
/* @__PURE__ */ c("p", {
|
|
219
|
-
className: "text-xs text-muted
|
|
219
|
+
className: "text-xs text-text-muted mt-1",
|
|
220
220
|
children: "How often the quota usage counter is reset to zero"
|
|
221
221
|
})
|
|
222
222
|
] })
|
|
@@ -224,11 +224,11 @@ var d = () => {
|
|
|
224
224
|
})]
|
|
225
225
|
}),
|
|
226
226
|
/* @__PURE__ */ l("div", {
|
|
227
|
-
className: "border border-border rounded-
|
|
227
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
228
228
|
children: [/* @__PURE__ */ c("div", {
|
|
229
|
-
className: "p-4 border-b border-border bg-
|
|
229
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
230
230
|
children: /* @__PURE__ */ c("h2", {
|
|
231
|
-
className: "font-semibold text-
|
|
231
|
+
className: "font-semibold text-text-primary",
|
|
232
232
|
children: "Limits Configuration"
|
|
233
233
|
})
|
|
234
234
|
}), /* @__PURE__ */ l("div", {
|
|
@@ -236,13 +236,13 @@ var d = () => {
|
|
|
236
236
|
children: [
|
|
237
237
|
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("label", {
|
|
238
238
|
htmlFor: "limitType",
|
|
239
|
-
className: "block text-sm font-medium text-
|
|
239
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
240
240
|
children: "Limit Type *"
|
|
241
241
|
}), /* @__PURE__ */ l("select", {
|
|
242
242
|
id: "limitType",
|
|
243
243
|
value: C,
|
|
244
244
|
onChange: (e) => w(e.target.value),
|
|
245
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
245
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
246
246
|
children: [
|
|
247
247
|
/* @__PURE__ */ c("option", {
|
|
248
248
|
value: "numeric",
|
|
@@ -265,7 +265,7 @@ var d = () => {
|
|
|
265
265
|
/* @__PURE__ */ l("div", { children: [
|
|
266
266
|
/* @__PURE__ */ c("label", {
|
|
267
267
|
htmlFor: "limitValue",
|
|
268
|
-
className: "block text-sm font-medium text-
|
|
268
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
269
269
|
children: "Limit Value *"
|
|
270
270
|
}),
|
|
271
271
|
/* @__PURE__ */ c("input", {
|
|
@@ -274,19 +274,19 @@ var d = () => {
|
|
|
274
274
|
min: "0",
|
|
275
275
|
value: T,
|
|
276
276
|
onChange: (e) => E(e.target.value),
|
|
277
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
277
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
278
278
|
placeholder: "1000",
|
|
279
279
|
required: !0
|
|
280
280
|
}),
|
|
281
281
|
/* @__PURE__ */ c("p", {
|
|
282
|
-
className: "text-xs text-muted
|
|
282
|
+
className: "text-xs text-text-muted mt-1",
|
|
283
283
|
children: "The maximum limit value for this quota"
|
|
284
284
|
})
|
|
285
285
|
] }),
|
|
286
286
|
/* @__PURE__ */ l("div", { children: [
|
|
287
287
|
/* @__PURE__ */ c("label", {
|
|
288
288
|
htmlFor: "unit",
|
|
289
|
-
className: "block text-sm font-medium text-
|
|
289
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
290
290
|
children: "Unit *"
|
|
291
291
|
}),
|
|
292
292
|
/* @__PURE__ */ c("input", {
|
|
@@ -294,12 +294,12 @@ var d = () => {
|
|
|
294
294
|
type: "text",
|
|
295
295
|
value: D,
|
|
296
296
|
onChange: (e) => O(e.target.value),
|
|
297
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
297
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
298
298
|
placeholder: "e.g., bots, GB, MB, seats, workflow runs",
|
|
299
299
|
required: !0
|
|
300
300
|
}),
|
|
301
301
|
/* @__PURE__ */ c("p", {
|
|
302
|
-
className: "text-xs text-muted
|
|
302
|
+
className: "text-xs text-text-muted mt-1",
|
|
303
303
|
children: "The unit of measurement displayed with usage values (e.g., \"2/6 bots\")"
|
|
304
304
|
})
|
|
305
305
|
] })
|
|
@@ -311,12 +311,12 @@ var d = () => {
|
|
|
311
311
|
children: [/* @__PURE__ */ c("button", {
|
|
312
312
|
type: "submit",
|
|
313
313
|
disabled: g,
|
|
314
|
-
className: "px-6 py-2 text-sm font-medium bg-primary text-primary-
|
|
314
|
+
className: "px-6 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50",
|
|
315
315
|
children: g ? f("billing.quota.creating", "Creating...") : f("billing.quota.createQuota", "Create Quota")
|
|
316
316
|
}), /* @__PURE__ */ c("button", {
|
|
317
317
|
type: "button",
|
|
318
318
|
onClick: () => p("/quotas"),
|
|
319
|
-
className: "px-6 py-2 text-sm font-medium border border-border text-
|
|
319
|
+
className: "px-6 py-2 text-sm font-medium border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors",
|
|
320
320
|
children: "Cancel"
|
|
321
321
|
})]
|
|
322
322
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuotaTemplateCreatePage.js","names":[],"sources":["../../../../../src/billing/modules/quota/pages/QuotaTemplateCreatePage.tsx"],"sourcesContent":["/**\n * Quota Module - Quota Template Create Page\n * Form to create a new quota template\n */\n\nimport { useState, type FC, type FormEvent } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useQuotaTemplateMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader } from '../../../shared/components';\nimport { QuotaType, QuotaResetPeriod, type CreateQuotaInput } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const QuotaTemplateCreatePage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const { createQuota, isCreating } = useQuotaTemplateMutations();\n\n // Form state\n const [name, setName] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [limitType, setLimitType] = useState('numeric');\n const [limitValue, setLimitValue] = useState('');\n const [unit, setUnit] = useState('');\n const [quotaType, setQuotaType] = useState<QuotaType>(QuotaType.PRODUCT_SPECIFIC);\n const [reusable, setReusable] = useState(false);\n const [resetPeriod, setResetPeriod] = useState<QuotaResetPeriod>(QuotaResetPeriod.NEVER);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState(false);\n\n // Permission check\n if (!permissions.canManageQuotas) {\n return <AccessDenied message=\"You don't have permission to create quotas.\" />;\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError(null);\n setSuccess(false);\n\n // Validation\n if (!name.trim()) {\n setError('Quota name is required');\n return;\n }\n if (!limitValue || isNaN(Number(limitValue)) || Number(limitValue) < 0) {\n setError('Valid limit value is required');\n return;\n }\n if (!unit.trim()) {\n setError('Unit is required (e.g., bots, GB, seats)');\n return;\n }\n\n const input: CreateQuotaInput = {\n name: name.trim(),\n limits: {\n type: limitType,\n value: Number(limitValue),\n unit: unit.trim(),\n },\n quotaType,\n reusable,\n resetPeriod,\n context: {\n displayName: displayName.trim() || name.trim(),\n description: description.trim(),\n },\n };\n\n try {\n await createQuota(input);\n setSuccess(true);\n // Navigate back after short delay\n setTimeout(() => navigateTo('/quotas'), 1500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to create quota');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader title=\"Create New Quota\" description=\"Set up a new quota template\" />\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-6\">\n {/* Error/Success Messages */}\n {error && (\n <div className=\"p-4 bg-status-error-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n {success && (\n <div className=\"p-4 bg-status-success-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-success-text\">\n Quota created successfully! Redirecting…\n </p>\n </div>\n )}\n\n {/* Basic Info */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Basic Information</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Machine Key (name) */}\n <div>\n <label htmlFor=\"name\" className=\"block text-sm font-medium text-foreground mb-1\">\n Quota Key *\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary font-mono text-sm\"\n placeholder=\"e.g., sessions-started, tunnels-created\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Internal machine key, must match the <code>quotaName</code> used in{' '}\n <code>@usage</code> directives. Never shown to users.\n </p>\n </div>\n\n {/* Display Name */}\n <div>\n <label\n htmlFor=\"displayName\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Display Name *\n </label>\n <input\n id=\"displayName\"\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., Tunnels, Session Starts, Webhooks\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Human-readable name shown to users in billing and usage UI.\n </p>\n </div>\n\n {/* Description */}\n <div>\n <label\n htmlFor=\"description\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Description\n </label>\n <textarea\n id=\"description\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary resize-none\"\n placeholder=\"e.g., Active tunnels created through VibeControls (slot freed on delete)\"\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Short explanation shown in billing and usage detail views.\n </p>\n </div>\n\n {/* Quota Type */}\n <div>\n <label htmlFor=\"quotaType\" className=\"block text-sm font-medium text-foreground mb-1\">\n Quota Type *\n </label>\n <select\n id=\"quotaType\"\n value={quotaType}\n onChange={(e) => setQuotaType(e.target.value as QuotaType)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value={QuotaType.PRODUCT_SPECIFIC}>Product Specific</option>\n <option value={QuotaType.POOLED}>Pooled</option>\n </select>\n <p className=\"text-xs text-muted-foreground mt-1\">\n {quotaType === QuotaType.POOLED\n ? 'Shared across all products'\n : 'Specific to individual products'}\n </p>\n </div>\n\n {/* Reusable */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"reusable\"\n type=\"checkbox\"\n checked={reusable}\n onChange={(e) => setReusable(e.target.checked)}\n className=\"size-4 rounded border-border text-primary focus:ring-primary\"\n />\n <div>\n <label htmlFor=\"reusable\" className=\"text-sm font-medium text-foreground\">\n Reusable Quota\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Enable for quotas like seats or bots that can be freed up\n </p>\n </div>\n </div>\n\n {/* Reset Period */}\n <div>\n <label\n htmlFor=\"resetPeriod\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Reset Period\n </label>\n <select\n id=\"resetPeriod\"\n value={resetPeriod}\n onChange={(e) => setResetPeriod(e.target.value as QuotaResetPeriod)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value={QuotaResetPeriod.NEVER}>Never (one-time limit)</option>\n <option value={QuotaResetPeriod.DAILY}>Daily (resets every day)</option>\n <option value={QuotaResetPeriod.MONTHLY}>Monthly (resets every month)</option>\n </select>\n <p className=\"text-xs text-muted-foreground mt-1\">\n How often the quota usage counter is reset to zero\n </p>\n </div>\n </div>\n </div>\n\n {/* Limits Configuration */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Limits Configuration</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Limit Type */}\n <div>\n <label htmlFor=\"limitType\" className=\"block text-sm font-medium text-foreground mb-1\">\n Limit Type *\n </label>\n <select\n id=\"limitType\"\n value={limitType}\n onChange={(e) => setLimitType(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"numeric\">Numeric (count)</option>\n <option value=\"storage\">Storage (bytes)</option>\n <option value=\"duration\">Duration (seconds)</option>\n <option value=\"percentage\">Percentage</option>\n </select>\n </div>\n\n {/* Limit Value */}\n <div>\n <label\n htmlFor=\"limitValue\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Limit Value *\n </label>\n <input\n id=\"limitValue\"\n type=\"number\"\n min=\"0\"\n value={limitValue}\n onChange={(e) => setLimitValue(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"1000\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The maximum limit value for this quota\n </p>\n </div>\n\n {/* Unit */}\n <div>\n <label htmlFor=\"unit\" className=\"block text-sm font-medium text-foreground mb-1\">\n Unit *\n </label>\n <input\n id=\"unit\"\n type=\"text\"\n value={unit}\n onChange={(e) => setUnit(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., bots, GB, MB, seats, workflow runs\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The unit of measurement displayed with usage values (e.g., "2/6 bots")\n </p>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-3 pt-4\">\n <button\n type=\"submit\"\n disabled={isCreating}\n className=\"px-6 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {isCreating\n ? tr('billing.quota.creating', 'Creating...')\n : tr('billing.quota.createQuota', 'Create Quota')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/quotas')}\n className=\"px-6 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QuotaTemplateCreatePage.js","names":[],"sources":["../../../../../src/billing/modules/quota/pages/QuotaTemplateCreatePage.tsx"],"sourcesContent":["/**\n * Quota Module - Quota Template Create Page\n * Form to create a new quota template\n */\n\nimport { useState, type FC, type FormEvent } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useQuotaTemplateMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader } from '../../../shared/components';\nimport { QuotaType, QuotaResetPeriod, type CreateQuotaInput } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const QuotaTemplateCreatePage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const { createQuota, isCreating } = useQuotaTemplateMutations();\n\n // Form state\n const [name, setName] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [limitType, setLimitType] = useState('numeric');\n const [limitValue, setLimitValue] = useState('');\n const [unit, setUnit] = useState('');\n const [quotaType, setQuotaType] = useState<QuotaType>(QuotaType.PRODUCT_SPECIFIC);\n const [reusable, setReusable] = useState(false);\n const [resetPeriod, setResetPeriod] = useState<QuotaResetPeriod>(QuotaResetPeriod.NEVER);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState(false);\n\n // Permission check\n if (!permissions.canManageQuotas) {\n return <AccessDenied message=\"You don't have permission to create quotas.\" />;\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError(null);\n setSuccess(false);\n\n // Validation\n if (!name.trim()) {\n setError('Quota name is required');\n return;\n }\n if (!limitValue || isNaN(Number(limitValue)) || Number(limitValue) < 0) {\n setError('Valid limit value is required');\n return;\n }\n if (!unit.trim()) {\n setError('Unit is required (e.g., bots, GB, seats)');\n return;\n }\n\n const input: CreateQuotaInput = {\n name: name.trim(),\n limits: {\n type: limitType,\n value: Number(limitValue),\n unit: unit.trim(),\n },\n quotaType,\n reusable,\n resetPeriod,\n context: {\n displayName: displayName.trim() || name.trim(),\n description: description.trim(),\n },\n };\n\n try {\n await createQuota(input);\n setSuccess(true);\n // Navigate back after short delay\n setTimeout(() => navigateTo('/quotas'), 1500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to create quota');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader title=\"Create New Quota\" description=\"Set up a new quota template\" />\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-6\">\n {/* Error/Success Messages */}\n {error && (\n <div className=\"p-4 bg-status-error-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n {success && (\n <div className=\"p-4 bg-status-success-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-success-text\">\n Quota created successfully! Redirecting…\n </p>\n </div>\n )}\n\n {/* Basic Info */}\n <div className=\"border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">Basic Information</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Machine Key (name) */}\n <div>\n <label htmlFor=\"name\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Quota Key *\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono text-sm\"\n placeholder=\"e.g., sessions-started, tunnels-created\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n Internal machine key, must match the <code>quotaName</code> used in{' '}\n <code>@usage</code> directives. Never shown to users.\n </p>\n </div>\n\n {/* Display Name */}\n <div>\n <label\n htmlFor=\"displayName\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Display Name *\n </label>\n <input\n id=\"displayName\"\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n placeholder=\"e.g., Tunnels, Session Starts, Webhooks\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n Human-readable name shown to users in billing and usage UI.\n </p>\n </div>\n\n {/* Description */}\n <div>\n <label\n htmlFor=\"description\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Description\n </label>\n <textarea\n id=\"description\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] resize-none\"\n placeholder=\"e.g., Active tunnels created through VibeControls (slot freed on delete)\"\n />\n <p className=\"text-xs text-text-muted mt-1\">\n Short explanation shown in billing and usage detail views.\n </p>\n </div>\n\n {/* Quota Type */}\n <div>\n <label\n htmlFor=\"quotaType\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Quota Type *\n </label>\n <select\n id=\"quotaType\"\n value={quotaType}\n onChange={(e) => setQuotaType(e.target.value as QuotaType)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value={QuotaType.PRODUCT_SPECIFIC}>Product Specific</option>\n <option value={QuotaType.POOLED}>Pooled</option>\n </select>\n <p className=\"text-xs text-text-muted mt-1\">\n {quotaType === QuotaType.POOLED\n ? 'Shared across all products'\n : 'Specific to individual products'}\n </p>\n </div>\n\n {/* Reusable */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"reusable\"\n type=\"checkbox\"\n checked={reusable}\n onChange={(e) => setReusable(e.target.checked)}\n className=\"size-4 rounded border-border-subtle text-text-link focus:ring-[var(--color-focus-ring)]\"\n />\n <div>\n <label htmlFor=\"reusable\" className=\"text-sm font-medium text-text-primary\">\n Reusable Quota\n </label>\n <p className=\"text-xs text-text-muted\">\n Enable for quotas like seats or bots that can be freed up\n </p>\n </div>\n </div>\n\n {/* Reset Period */}\n <div>\n <label\n htmlFor=\"resetPeriod\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Reset Period\n </label>\n <select\n id=\"resetPeriod\"\n value={resetPeriod}\n onChange={(e) => setResetPeriod(e.target.value as QuotaResetPeriod)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value={QuotaResetPeriod.NEVER}>Never (one-time limit)</option>\n <option value={QuotaResetPeriod.DAILY}>Daily (resets every day)</option>\n <option value={QuotaResetPeriod.MONTHLY}>Monthly (resets every month)</option>\n </select>\n <p className=\"text-xs text-text-muted mt-1\">\n How often the quota usage counter is reset to zero\n </p>\n </div>\n </div>\n </div>\n\n {/* Limits Configuration */}\n <div className=\"border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">Limits Configuration</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Limit Type */}\n <div>\n <label\n htmlFor=\"limitType\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Limit Type *\n </label>\n <select\n id=\"limitType\"\n value={limitType}\n onChange={(e) => setLimitType(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"numeric\">Numeric (count)</option>\n <option value=\"storage\">Storage (bytes)</option>\n <option value=\"duration\">Duration (seconds)</option>\n <option value=\"percentage\">Percentage</option>\n </select>\n </div>\n\n {/* Limit Value */}\n <div>\n <label\n htmlFor=\"limitValue\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Limit Value *\n </label>\n <input\n id=\"limitValue\"\n type=\"number\"\n min=\"0\"\n value={limitValue}\n onChange={(e) => setLimitValue(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n placeholder=\"1000\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">The maximum limit value for this quota</p>\n </div>\n\n {/* Unit */}\n <div>\n <label htmlFor=\"unit\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Unit *\n </label>\n <input\n id=\"unit\"\n type=\"text\"\n value={unit}\n onChange={(e) => setUnit(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n placeholder=\"e.g., bots, GB, MB, seats, workflow runs\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n The unit of measurement displayed with usage values (e.g., "2/6 bots")\n </p>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-3 pt-4\">\n <button\n type=\"submit\"\n disabled={isCreating}\n className=\"px-6 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50\"\n >\n {isCreating\n ? tr('billing.quota.creating', 'Creating...')\n : tr('billing.quota.createQuota', 'Create Quota')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/quotas')}\n className=\"px-6 py-2 text-sm font-medium border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -21,7 +21,7 @@ var p = () => {
|
|
|
21
21
|
if (!_.canViewQuotas) return /* @__PURE__ */ u(e, { message: "You don't have permission to view quota details." });
|
|
22
22
|
if (y) return /* @__PURE__ */ d("div", {
|
|
23
23
|
className: "space-y-6 p-6",
|
|
24
|
-
children: [/* @__PURE__ */ u("div", { className: "h-8 w-48 bg-
|
|
24
|
+
children: [/* @__PURE__ */ u("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ d("div", {
|
|
25
25
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
26
26
|
children: [/* @__PURE__ */ u("div", {
|
|
27
27
|
className: "lg:col-span-2 space-y-4",
|
|
@@ -29,8 +29,8 @@ var p = () => {
|
|
|
29
29
|
1,
|
|
30
30
|
2,
|
|
31
31
|
3
|
|
32
|
-
].map((e) => /* @__PURE__ */ u("div", { className: "h-24 bg-
|
|
33
|
-
}), /* @__PURE__ */ u("div", { className: "h-64 bg-
|
|
32
|
+
].map((e) => /* @__PURE__ */ u("div", { className: "h-24 bg-bg-sunken animate-pulse rounded" }, e))
|
|
33
|
+
}), /* @__PURE__ */ u("div", { className: "h-64 bg-bg-sunken animate-pulse rounded" })]
|
|
34
34
|
})]
|
|
35
35
|
});
|
|
36
36
|
if (b && i(b)) return /* @__PURE__ */ u("div", {
|
|
@@ -48,9 +48,9 @@ var p = () => {
|
|
|
48
48
|
className: "text-center space-y-4",
|
|
49
49
|
children: [
|
|
50
50
|
/* @__PURE__ */ u("div", {
|
|
51
|
-
className: "size-12 mx-auto rounded-full bg-
|
|
51
|
+
className: "size-12 mx-auto rounded-full bg-bg-sunken flex items-center justify-center",
|
|
52
52
|
children: /* @__PURE__ */ u("svg", {
|
|
53
|
-
className: "size-6 text-muted
|
|
53
|
+
className: "size-6 text-text-muted",
|
|
54
54
|
fill: "none",
|
|
55
55
|
viewBox: "0 0 24 24",
|
|
56
56
|
stroke: "currentColor",
|
|
@@ -63,17 +63,17 @@ var p = () => {
|
|
|
63
63
|
})
|
|
64
64
|
}),
|
|
65
65
|
/* @__PURE__ */ u("h2", {
|
|
66
|
-
className: "text-lg font-semibold text-
|
|
66
|
+
className: "text-lg font-semibold text-text-primary",
|
|
67
67
|
children: m("billing.quota.quotaNotFound", "Quota not found")
|
|
68
68
|
}),
|
|
69
69
|
/* @__PURE__ */ u("p", {
|
|
70
|
-
className: "text-sm text-muted
|
|
70
|
+
className: "text-sm text-text-muted",
|
|
71
71
|
children: "The quota you're looking for doesn't exist or has been removed."
|
|
72
72
|
}),
|
|
73
73
|
/* @__PURE__ */ u("button", {
|
|
74
74
|
type: "button",
|
|
75
75
|
onClick: () => g("/quotas"),
|
|
76
|
-
className: "px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
76
|
+
className: "px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors",
|
|
77
77
|
children: "Back to Quotas"
|
|
78
78
|
})
|
|
79
79
|
]
|
|
@@ -97,11 +97,11 @@ var p = () => {
|
|
|
97
97
|
className: "lg:col-span-2 space-y-6",
|
|
98
98
|
children: [
|
|
99
99
|
/* @__PURE__ */ d("div", {
|
|
100
|
-
className: "border border-border rounded-
|
|
100
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
101
101
|
children: [/* @__PURE__ */ u("div", {
|
|
102
|
-
className: "p-4 border-b border-border bg-
|
|
102
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
103
103
|
children: /* @__PURE__ */ u("h2", {
|
|
104
|
-
className: "font-semibold text-
|
|
104
|
+
className: "font-semibold text-text-primary",
|
|
105
105
|
children: m("billing.quota.limitsConfig", "Limits Configuration")
|
|
106
106
|
})
|
|
107
107
|
}), /* @__PURE__ */ u("div", {
|
|
@@ -110,24 +110,24 @@ var p = () => {
|
|
|
110
110
|
className: "grid grid-cols-3 gap-6",
|
|
111
111
|
children: [
|
|
112
112
|
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
113
|
-
className: "text-sm text-muted
|
|
113
|
+
className: "text-sm text-text-muted",
|
|
114
114
|
children: "Limit Type"
|
|
115
115
|
}), /* @__PURE__ */ u("p", {
|
|
116
|
-
className: "text-lg font-semibold text-
|
|
116
|
+
className: "text-lg font-semibold text-text-primary capitalize mt-1",
|
|
117
117
|
children: E
|
|
118
118
|
})] }),
|
|
119
119
|
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
120
|
-
className: "text-sm text-muted
|
|
120
|
+
className: "text-sm text-text-muted",
|
|
121
121
|
children: "Limit Value"
|
|
122
122
|
}), /* @__PURE__ */ u("p", {
|
|
123
|
-
className: "text-lg font-semibold text-
|
|
123
|
+
className: "text-lg font-semibold text-text-primary mt-1",
|
|
124
124
|
children: D.toLocaleString()
|
|
125
125
|
})] }),
|
|
126
126
|
/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
127
|
-
className: "text-sm text-muted
|
|
127
|
+
className: "text-sm text-text-muted",
|
|
128
128
|
children: "Unit"
|
|
129
129
|
}), /* @__PURE__ */ u("p", {
|
|
130
|
-
className: "text-lg font-semibold text-
|
|
130
|
+
className: "text-lg font-semibold text-text-primary mt-1",
|
|
131
131
|
children: O || "-"
|
|
132
132
|
})] })
|
|
133
133
|
]
|
|
@@ -135,54 +135,54 @@ var p = () => {
|
|
|
135
135
|
})]
|
|
136
136
|
}),
|
|
137
137
|
/* @__PURE__ */ d("div", {
|
|
138
|
-
className: "border border-border rounded-
|
|
138
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
139
139
|
children: [/* @__PURE__ */ u("div", {
|
|
140
|
-
className: "p-4 border-b border-border bg-
|
|
140
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
141
141
|
children: /* @__PURE__ */ u("h2", {
|
|
142
|
-
className: "font-semibold text-
|
|
142
|
+
className: "font-semibold text-text-primary",
|
|
143
143
|
children: m("billing.quota.properties", "Properties")
|
|
144
144
|
})
|
|
145
145
|
}), /* @__PURE__ */ d("div", {
|
|
146
146
|
className: "p-6 space-y-4",
|
|
147
147
|
children: [/* @__PURE__ */ d("div", {
|
|
148
|
-
className: "flex items-center justify-between p-3 border border-border rounded-lg",
|
|
148
|
+
className: "flex items-center justify-between p-3 border border-border-subtle rounded-lg",
|
|
149
149
|
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
150
|
-
className: "font-medium text-
|
|
150
|
+
className: "font-medium text-text-primary",
|
|
151
151
|
children: "Quota Type"
|
|
152
152
|
}), /* @__PURE__ */ u("p", {
|
|
153
|
-
className: "text-sm text-muted
|
|
153
|
+
className: "text-sm text-text-muted",
|
|
154
154
|
children: v.quotaType === "POOLED" ? "Shared across all products" : "Specific to individual products"
|
|
155
155
|
})] }), /* @__PURE__ */ u("span", {
|
|
156
|
-
className: `px-3 py-1 text-sm font-medium rounded ${v.quotaType === "POOLED" ? "bg-status-info-bg-subtle text-status-info-text" : "bg-accent-purple-subtle text-
|
|
156
|
+
className: `px-3 py-1 text-sm font-medium rounded ${v.quotaType === "POOLED" ? "bg-status-info-bg-subtle text-status-info-text" : "bg-accent-purple-subtle text-text-primary"}`,
|
|
157
157
|
children: v.quotaType === "POOLED" ? "Pooled" : "Product Specific"
|
|
158
158
|
})]
|
|
159
159
|
}), /* @__PURE__ */ d("div", {
|
|
160
|
-
className: "flex items-center justify-between p-3 border border-border rounded-lg",
|
|
160
|
+
className: "flex items-center justify-between p-3 border border-border-subtle rounded-lg",
|
|
161
161
|
children: [/* @__PURE__ */ d("div", { children: [/* @__PURE__ */ u("p", {
|
|
162
|
-
className: "font-medium text-
|
|
162
|
+
className: "font-medium text-text-primary",
|
|
163
163
|
children: "Reusable"
|
|
164
164
|
}), /* @__PURE__ */ u("p", {
|
|
165
|
-
className: "text-sm text-muted
|
|
165
|
+
className: "text-sm text-text-muted",
|
|
166
166
|
children: v.reusable ? "Quota can be freed up and reused (e.g., seats, bots)" : "Quota is consumed permanently (e.g., API calls, storage)"
|
|
167
167
|
})] }), /* @__PURE__ */ u("span", {
|
|
168
|
-
className: `px-3 py-1 text-sm font-medium rounded ${v.reusable ? "bg-status-success-bg-subtle text-status-success-text" : "bg-
|
|
168
|
+
className: `px-3 py-1 text-sm font-medium rounded ${v.reusable ? "bg-status-success-bg-subtle text-status-success-text" : "bg-bg-sunken text-text-muted"}`,
|
|
169
169
|
children: v.reusable ? "Yes" : "No"
|
|
170
170
|
})]
|
|
171
171
|
})]
|
|
172
172
|
})]
|
|
173
173
|
}),
|
|
174
174
|
/* @__PURE__ */ d("div", {
|
|
175
|
-
className: "border border-border rounded-
|
|
175
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
176
176
|
children: [/* @__PURE__ */ u("div", {
|
|
177
|
-
className: "p-4 border-b border-border bg-
|
|
177
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
178
178
|
children: /* @__PURE__ */ u("h2", {
|
|
179
|
-
className: "font-semibold text-
|
|
179
|
+
className: "font-semibold text-text-primary",
|
|
180
180
|
children: "Limits (Raw JSON)"
|
|
181
181
|
})
|
|
182
182
|
}), /* @__PURE__ */ u("div", {
|
|
183
183
|
className: "p-4",
|
|
184
184
|
children: /* @__PURE__ */ u("pre", {
|
|
185
|
-
className: "text-sm text-
|
|
185
|
+
className: "text-sm text-text-primary bg-bg-sunken/50 p-4 rounded-lg overflow-auto",
|
|
186
186
|
children: JSON.stringify(v.limits, null, 2)
|
|
187
187
|
})
|
|
188
188
|
})]
|
|
@@ -192,11 +192,11 @@ var p = () => {
|
|
|
192
192
|
className: "space-y-6",
|
|
193
193
|
children: [
|
|
194
194
|
/* @__PURE__ */ d("div", {
|
|
195
|
-
className: "border border-border rounded-
|
|
195
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
196
196
|
children: [/* @__PURE__ */ u("div", {
|
|
197
|
-
className: "p-4 border-b border-border bg-
|
|
197
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
198
198
|
children: /* @__PURE__ */ u("h2", {
|
|
199
|
-
className: "font-semibold text-
|
|
199
|
+
className: "font-semibold text-text-primary",
|
|
200
200
|
children: "Status"
|
|
201
201
|
})
|
|
202
202
|
}), /* @__PURE__ */ d("div", {
|
|
@@ -205,30 +205,30 @@ var p = () => {
|
|
|
205
205
|
/* @__PURE__ */ d("div", {
|
|
206
206
|
className: "flex items-center justify-between",
|
|
207
207
|
children: [/* @__PURE__ */ u("span", {
|
|
208
|
-
className: "text-sm text-muted
|
|
208
|
+
className: "text-sm text-text-muted",
|
|
209
209
|
children: "Status"
|
|
210
210
|
}), /* @__PURE__ */ u("span", {
|
|
211
|
-
className: `px-2 py-1 text-xs font-medium rounded ${v.isActive ? "bg-status-success-bg-subtle text-status-success-text" : "bg-
|
|
211
|
+
className: `px-2 py-1 text-xs font-medium rounded ${v.isActive ? "bg-status-success-bg-subtle text-status-success-text" : "bg-bg-sunken text-text-muted"}`,
|
|
212
212
|
children: v.isActive ? "Active" : "Inactive"
|
|
213
213
|
})]
|
|
214
214
|
}),
|
|
215
215
|
/* @__PURE__ */ d("div", {
|
|
216
216
|
className: "flex items-center justify-between",
|
|
217
217
|
children: [/* @__PURE__ */ u("span", {
|
|
218
|
-
className: "text-sm text-muted
|
|
218
|
+
className: "text-sm text-text-muted",
|
|
219
219
|
children: "Created"
|
|
220
220
|
}), /* @__PURE__ */ u("span", {
|
|
221
|
-
className: "text-sm font-medium text-
|
|
221
|
+
className: "text-sm font-medium text-text-primary",
|
|
222
222
|
children: r(v.createdAt, "short")
|
|
223
223
|
})]
|
|
224
224
|
}),
|
|
225
225
|
/* @__PURE__ */ d("div", {
|
|
226
226
|
className: "flex items-center justify-between",
|
|
227
227
|
children: [/* @__PURE__ */ u("span", {
|
|
228
|
-
className: "text-sm text-muted
|
|
228
|
+
className: "text-sm text-text-muted",
|
|
229
229
|
children: "Updated"
|
|
230
230
|
}), /* @__PURE__ */ u("span", {
|
|
231
|
-
className: "text-sm font-medium text-
|
|
231
|
+
className: "text-sm font-medium text-text-primary",
|
|
232
232
|
children: r(v.updatedAt, "short")
|
|
233
233
|
})]
|
|
234
234
|
})
|
|
@@ -236,11 +236,11 @@ var p = () => {
|
|
|
236
236
|
})]
|
|
237
237
|
}),
|
|
238
238
|
_.canManageQuotas && /* @__PURE__ */ d("div", {
|
|
239
|
-
className: "border border-border rounded-
|
|
239
|
+
className: "border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]",
|
|
240
240
|
children: [/* @__PURE__ */ u("div", {
|
|
241
|
-
className: "p-4 border-b border-border bg-
|
|
241
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
242
242
|
children: /* @__PURE__ */ u("h2", {
|
|
243
|
-
className: "font-semibold text-
|
|
243
|
+
className: "font-semibold text-text-primary",
|
|
244
244
|
children: "Actions"
|
|
245
245
|
})
|
|
246
246
|
}), /* @__PURE__ */ d("div", {
|
|
@@ -248,13 +248,13 @@ var p = () => {
|
|
|
248
248
|
children: [/* @__PURE__ */ u("button", {
|
|
249
249
|
type: "button",
|
|
250
250
|
onClick: () => g(`/quotas/${v.id}/edit`),
|
|
251
|
-
className: "w-full px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
251
|
+
className: "w-full px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors",
|
|
252
252
|
children: "Edit Quota"
|
|
253
253
|
}), /* @__PURE__ */ u("button", {
|
|
254
254
|
type: "button",
|
|
255
255
|
onClick: w,
|
|
256
256
|
disabled: C,
|
|
257
|
-
className: `w-full px-4 py-2 text-sm font-medium border border-border rounded-md transition-colors disabled:opacity-50 ${v.isActive ? "text-
|
|
257
|
+
className: `w-full px-4 py-2 text-sm font-medium border border-border-subtle rounded-md transition-colors disabled:opacity-50 ${v.isActive ? "text-status-error-text hover:bg-status-error-bg-subtle" : "text-status-success-text hover:bg-status-success-bg-subtle"}`,
|
|
258
258
|
children: C ? "Processing..." : v.isActive ? "Deactivate Quota" : "Activate Quota"
|
|
259
259
|
})]
|
|
260
260
|
})]
|
|
@@ -262,7 +262,7 @@ var p = () => {
|
|
|
262
262
|
/* @__PURE__ */ u("button", {
|
|
263
263
|
type: "button",
|
|
264
264
|
onClick: () => g("/quotas"),
|
|
265
|
-
className: "w-full px-4 py-2 text-sm font-medium border border-border text-
|
|
265
|
+
className: "w-full px-4 py-2 text-sm font-medium border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors",
|
|
266
266
|
children: "Back to Quotas"
|
|
267
267
|
})
|
|
268
268
|
]
|