@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
|
@@ -33,14 +33,14 @@ var x = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, S = {
|
|
|
33
33
|
},
|
|
34
34
|
[c.Skipped]: {
|
|
35
35
|
label: "Closed",
|
|
36
|
-
className: "bg-
|
|
36
|
+
className: "bg-bg-sunken text-text-secondary border-border-subtle",
|
|
37
37
|
icon: ({ className: e }) => /* @__PURE__ */ v(_, { className: e })
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
40
|
function re({ status: e }) {
|
|
41
41
|
let t = S[e] ?? {
|
|
42
42
|
label: e,
|
|
43
|
-
className: "bg-
|
|
43
|
+
className: "bg-bg-sunken text-text-secondary border-border-subtle",
|
|
44
44
|
icon: ({ className: e }) => /* @__PURE__ */ v(p, { className: e })
|
|
45
45
|
}, n = t.icon;
|
|
46
46
|
return /* @__PURE__ */ y("span", {
|
|
@@ -138,24 +138,24 @@ var C = () => {
|
|
|
138
138
|
onClick: () => {
|
|
139
139
|
w(!0), L(!1);
|
|
140
140
|
},
|
|
141
|
-
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
141
|
+
className: "inline-flex items-center gap-2 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",
|
|
142
142
|
children: [/* @__PURE__ */ v(ee, { className: "size-4" }), _("billing.refunds.requestRefund", "Request Refund")]
|
|
143
143
|
})
|
|
144
144
|
}),
|
|
145
145
|
!R && z.length > 1 && /* @__PURE__ */ y("div", {
|
|
146
146
|
className: "flex items-center gap-3",
|
|
147
147
|
children: [
|
|
148
|
-
/* @__PURE__ */ v(m, { className: "size-4 text-
|
|
148
|
+
/* @__PURE__ */ v(m, { className: "size-4 text-text-secondary shrink-0" }),
|
|
149
149
|
/* @__PURE__ */ v("label", {
|
|
150
150
|
htmlFor: "accountSwitch",
|
|
151
|
-
className: "text-sm text-
|
|
151
|
+
className: "text-sm text-text-secondary shrink-0",
|
|
152
152
|
children: _("billing.refunds.account", "Billing account")
|
|
153
153
|
}),
|
|
154
154
|
/* @__PURE__ */ v("select", {
|
|
155
155
|
id: "accountSwitch",
|
|
156
156
|
value: B ?? "",
|
|
157
157
|
onChange: (e) => se(e.target.value),
|
|
158
|
-
className: "flex-1 px-3 py-1.5 border border-border rounded-
|
|
158
|
+
className: "flex-1 px-3 py-1.5 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm",
|
|
159
159
|
children: z.map((e) => /* @__PURE__ */ y("option", {
|
|
160
160
|
value: e.id,
|
|
161
161
|
children: [
|
|
@@ -185,17 +185,17 @@ var C = () => {
|
|
|
185
185
|
})]
|
|
186
186
|
}),
|
|
187
187
|
C && /* @__PURE__ */ y("div", {
|
|
188
|
-
className: "border border-border rounded-
|
|
188
|
+
className: "border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
|
|
189
189
|
children: [/* @__PURE__ */ y("div", {
|
|
190
|
-
className: "flex items-center justify-between p-4 border-b border-border bg-
|
|
190
|
+
className: "flex items-center justify-between p-4 border-b border-border-subtle bg-bg-sunken",
|
|
191
191
|
children: [/* @__PURE__ */ v("h2", {
|
|
192
|
-
className: "font-semibold text-
|
|
192
|
+
className: "font-semibold text-text-primary",
|
|
193
193
|
children: _("billing.refunds.newRequest", "New Refund Request")
|
|
194
194
|
}), /* @__PURE__ */ v("button", {
|
|
195
195
|
type: "button",
|
|
196
196
|
onClick: $,
|
|
197
|
-
className: "p-1 rounded hover:bg-
|
|
198
|
-
children: /* @__PURE__ */ v(g, { className: "size-4 text-
|
|
197
|
+
className: "p-1 rounded hover:bg-bg-sunken transition-colors",
|
|
198
|
+
children: /* @__PURE__ */ v(g, { className: "size-4 text-text-secondary" })
|
|
199
199
|
})]
|
|
200
200
|
}), /* @__PURE__ */ y("form", {
|
|
201
201
|
onSubmit: fe,
|
|
@@ -211,7 +211,7 @@ var C = () => {
|
|
|
211
211
|
/* @__PURE__ */ y("div", { children: [
|
|
212
212
|
/* @__PURE__ */ y("label", {
|
|
213
213
|
htmlFor: "txnId",
|
|
214
|
-
className: "block text-sm font-medium text-
|
|
214
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
215
215
|
children: [_("billing.refunds.transactionId", "Transaction ID"), " *"]
|
|
216
216
|
}),
|
|
217
217
|
/* @__PURE__ */ y("div", {
|
|
@@ -222,41 +222,41 @@ var C = () => {
|
|
|
222
222
|
value: T,
|
|
223
223
|
onChange: (e) => oe(e.target.value),
|
|
224
224
|
placeholder: "Paste your transaction ID...",
|
|
225
|
-
className: "w-full pl-3 pr-9 py-2 border border-border rounded-
|
|
225
|
+
className: "w-full pl-3 pr-9 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm font-mono"
|
|
226
226
|
}), /* @__PURE__ */ v("div", {
|
|
227
|
-
className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-
|
|
227
|
+
className: "absolute right-2.5 top-1/2 -translate-y-1/2 text-text-secondary",
|
|
228
228
|
children: G ? /* @__PURE__ */ v(h, { className: "size-4 animate-spin" }) : /* @__PURE__ */ v(ne, { className: "size-4" })
|
|
229
229
|
})]
|
|
230
230
|
}),
|
|
231
231
|
D && /* @__PURE__ */ y("div", {
|
|
232
|
-
className: "mt-2 p-3 rounded-
|
|
232
|
+
className: "mt-2 p-3 rounded-button border border-status-success-border bg-status-success-bg/10 text-sm space-y-0.5",
|
|
233
233
|
children: [/* @__PURE__ */ y("div", {
|
|
234
234
|
className: "flex items-center gap-2",
|
|
235
235
|
children: [
|
|
236
236
|
/* @__PURE__ */ v(f, { className: "size-3.5 text-status-success-text shrink-0" }),
|
|
237
237
|
/* @__PURE__ */ v("span", {
|
|
238
|
-
className: "font-medium text-
|
|
238
|
+
className: "font-medium text-text-primary",
|
|
239
239
|
children: t(D.amount, D.currency)
|
|
240
240
|
}),
|
|
241
241
|
/* @__PURE__ */ v("span", {
|
|
242
|
-
className: "text-
|
|
242
|
+
className: "text-text-secondary",
|
|
243
243
|
children: "·"
|
|
244
244
|
}),
|
|
245
245
|
/* @__PURE__ */ v("span", {
|
|
246
|
-
className: "text-
|
|
246
|
+
className: "text-text-secondary",
|
|
247
247
|
children: n(D.createdAt)
|
|
248
248
|
}),
|
|
249
249
|
D.stripePaymentId && /* @__PURE__ */ v("span", {
|
|
250
|
-
className: "text-xs text-
|
|
250
|
+
className: "text-xs text-text-secondary",
|
|
251
251
|
children: "Stripe"
|
|
252
252
|
}),
|
|
253
253
|
D.razorpayPaymentId && /* @__PURE__ */ v("span", {
|
|
254
|
-
className: "text-xs text-
|
|
254
|
+
className: "text-xs text-text-secondary",
|
|
255
255
|
children: "Razorpay"
|
|
256
256
|
})
|
|
257
257
|
]
|
|
258
258
|
}), D.description && /* @__PURE__ */ v("p", {
|
|
259
|
-
className: "text-xs text-
|
|
259
|
+
className: "text-xs text-text-secondary pl-5",
|
|
260
260
|
children: D.description
|
|
261
261
|
})]
|
|
262
262
|
}),
|
|
@@ -265,13 +265,13 @@ var C = () => {
|
|
|
265
265
|
children: _("billing.refunds.txnNotFound", "Transaction not found in this billing account.")
|
|
266
266
|
}),
|
|
267
267
|
!x.test(T.trim()) && T.length > 4 && /* @__PURE__ */ v("p", {
|
|
268
|
-
className: "mt-1 text-xs text-
|
|
268
|
+
className: "mt-1 text-xs text-text-secondary",
|
|
269
269
|
children: _("billing.refunds.txnIdHint", "Transaction IDs look like: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
|
|
270
270
|
})
|
|
271
271
|
] }),
|
|
272
272
|
D && /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ y("label", {
|
|
273
273
|
htmlFor: "refundAmount",
|
|
274
|
-
className: "block text-sm font-medium text-
|
|
274
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
275
275
|
children: [_("billing.refunds.amount", "Refund Amount"), " *"]
|
|
276
276
|
}), /* @__PURE__ */ y("div", {
|
|
277
277
|
className: "flex items-center gap-2",
|
|
@@ -285,22 +285,22 @@ var C = () => {
|
|
|
285
285
|
value: N,
|
|
286
286
|
onChange: (e) => P(e.target.value),
|
|
287
287
|
required: !0,
|
|
288
|
-
className: "w-40 px-3 py-2 border border-border rounded-
|
|
288
|
+
className: "w-40 px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm",
|
|
289
289
|
placeholder: "0.00"
|
|
290
290
|
}),
|
|
291
291
|
/* @__PURE__ */ v("span", {
|
|
292
|
-
className: "text-sm text-
|
|
292
|
+
className: "text-sm text-text-secondary",
|
|
293
293
|
children: D.currency ?? H?.currency ?? "USD"
|
|
294
294
|
}),
|
|
295
295
|
/* @__PURE__ */ y("span", {
|
|
296
|
-
className: "text-xs text-
|
|
296
|
+
className: "text-xs text-text-secondary",
|
|
297
297
|
children: ["max ", t(D.amount, D.currency)]
|
|
298
298
|
})
|
|
299
299
|
]
|
|
300
300
|
})] }),
|
|
301
301
|
/* @__PURE__ */ y("div", { children: [/* @__PURE__ */ y("label", {
|
|
302
302
|
htmlFor: "reason",
|
|
303
|
-
className: "block text-sm font-medium text-
|
|
303
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
304
304
|
children: [_("billing.refunds.reason", "Reason for refund"), " *"]
|
|
305
305
|
}), /* @__PURE__ */ v("textarea", {
|
|
306
306
|
id: "reason",
|
|
@@ -308,7 +308,7 @@ var C = () => {
|
|
|
308
308
|
onChange: (e) => M(e.target.value),
|
|
309
309
|
required: !0,
|
|
310
310
|
rows: 3,
|
|
311
|
-
className: "w-full px-3 py-2 border border-border rounded-
|
|
311
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm resize-none",
|
|
312
312
|
placeholder: _("billing.refunds.reasonPlaceholder", "Describe why you are requesting a refund...")
|
|
313
313
|
})] }),
|
|
314
314
|
/* @__PURE__ */ y("div", {
|
|
@@ -316,12 +316,12 @@ var C = () => {
|
|
|
316
316
|
children: [/* @__PURE__ */ v("button", {
|
|
317
317
|
type: "submit",
|
|
318
318
|
disabled: X || !D || !j.trim() || !N,
|
|
319
|
-
className: "px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
319
|
+
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 disabled:opacity-50 disabled:cursor-not-allowed",
|
|
320
320
|
children: X ? _("billing.refunds.submitting", "Submitting...") : _("billing.refunds.submitRequest", "Submit Request")
|
|
321
321
|
}), /* @__PURE__ */ v("button", {
|
|
322
322
|
type: "button",
|
|
323
323
|
onClick: $,
|
|
324
|
-
className: "px-4 py-2 text-sm border border-border text-
|
|
324
|
+
className: "px-4 py-2 text-sm border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors",
|
|
325
325
|
children: _("billing.common.cancel", "Cancel")
|
|
326
326
|
})]
|
|
327
327
|
})
|
|
@@ -329,33 +329,33 @@ var C = () => {
|
|
|
329
329
|
})]
|
|
330
330
|
}),
|
|
331
331
|
/* @__PURE__ */ y("div", {
|
|
332
|
-
className: "border border-border rounded-
|
|
332
|
+
className: "border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
|
|
333
333
|
children: [/* @__PURE__ */ v("div", {
|
|
334
|
-
className: "p-4 border-b border-border bg-
|
|
334
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken",
|
|
335
335
|
children: /* @__PURE__ */ v("h2", {
|
|
336
|
-
className: "font-semibold text-
|
|
336
|
+
className: "font-semibold text-text-primary",
|
|
337
337
|
children: _("billing.refunds.history", "Refund History")
|
|
338
338
|
})
|
|
339
339
|
}), R || le ? /* @__PURE__ */ v("div", {
|
|
340
340
|
className: "p-8 flex items-center justify-center",
|
|
341
|
-
children: /* @__PURE__ */ v(h, { className: "size-5 animate-spin text-
|
|
341
|
+
children: /* @__PURE__ */ v(h, { className: "size-5 animate-spin text-text-secondary" })
|
|
342
342
|
}) : Y.length === 0 ? /* @__PURE__ */ y("div", {
|
|
343
343
|
className: "p-10 flex flex-col items-center text-center gap-3",
|
|
344
344
|
children: [
|
|
345
|
-
/* @__PURE__ */ v(te, { className: "size-8 text-
|
|
345
|
+
/* @__PURE__ */ v(te, { className: "size-8 text-text-secondary" }),
|
|
346
346
|
/* @__PURE__ */ v("p", {
|
|
347
|
-
className: "text-sm font-medium text-
|
|
347
|
+
className: "text-sm font-medium text-text-primary",
|
|
348
348
|
children: _("billing.refunds.noRefunds", "No refund requests yet")
|
|
349
349
|
}),
|
|
350
350
|
/* @__PURE__ */ v("p", {
|
|
351
|
-
className: "text-xs text-
|
|
351
|
+
className: "text-xs text-text-secondary max-w-sm",
|
|
352
352
|
children: _("billing.refunds.noRefundsHint", "If you have an issue with a payment, click \"Request Refund\" to get started.")
|
|
353
353
|
})
|
|
354
354
|
]
|
|
355
355
|
}) : /* @__PURE__ */ v("ul", {
|
|
356
|
-
className: "divide-y divide-border",
|
|
356
|
+
className: "divide-y divide-border-subtle",
|
|
357
357
|
children: Y.map((e) => /* @__PURE__ */ y("li", {
|
|
358
|
-
className: "flex items-start gap-4 p-4 hover:bg-
|
|
358
|
+
className: "flex items-start gap-4 p-4 hover:bg-bg-sunken transition-colors",
|
|
359
359
|
children: [/* @__PURE__ */ y("div", {
|
|
360
360
|
className: "flex-1 min-w-0",
|
|
361
361
|
children: [
|
|
@@ -363,18 +363,18 @@ var C = () => {
|
|
|
363
363
|
className: "flex items-center gap-2 flex-wrap",
|
|
364
364
|
children: [
|
|
365
365
|
/* @__PURE__ */ v("span", {
|
|
366
|
-
className: "text-sm font-medium text-
|
|
366
|
+
className: "text-sm font-medium text-text-primary",
|
|
367
367
|
children: t(e.amount, e.currency)
|
|
368
368
|
}),
|
|
369
369
|
/* @__PURE__ */ v(re, { status: e.status }),
|
|
370
370
|
e.purchaseDetail && /* @__PURE__ */ v("span", {
|
|
371
|
-
className: "text-xs text-
|
|
371
|
+
className: "text-xs text-text-secondary truncate",
|
|
372
372
|
children: e.purchaseDetail
|
|
373
373
|
})
|
|
374
374
|
]
|
|
375
375
|
}),
|
|
376
376
|
e.reason && /* @__PURE__ */ v("p", {
|
|
377
|
-
className: "text-xs text-
|
|
377
|
+
className: "text-xs text-text-secondary mt-1 line-clamp-2",
|
|
378
378
|
children: e.reason
|
|
379
379
|
}),
|
|
380
380
|
e.errorMessage && e.status === c.Failed && /* @__PURE__ */ v("p", {
|
|
@@ -385,10 +385,10 @@ var C = () => {
|
|
|
385
385
|
}), /* @__PURE__ */ y("div", {
|
|
386
386
|
className: "text-right shrink-0",
|
|
387
387
|
children: [/* @__PURE__ */ v("p", {
|
|
388
|
-
className: "text-xs text-
|
|
388
|
+
className: "text-xs text-text-secondary",
|
|
389
389
|
children: n(e.createdAt)
|
|
390
390
|
}), e.processedAt && /* @__PURE__ */ y("p", {
|
|
391
|
-
className: "text-xs text-
|
|
391
|
+
className: "text-xs text-text-secondary mt-0.5",
|
|
392
392
|
children: ["Processed ", n(e.processedAt)]
|
|
393
393
|
})]
|
|
394
394
|
})]
|
|
@@ -396,7 +396,7 @@ var C = () => {
|
|
|
396
396
|
})]
|
|
397
397
|
}),
|
|
398
398
|
/* @__PURE__ */ y("p", {
|
|
399
|
-
className: "text-xs text-
|
|
399
|
+
className: "text-xs text-text-secondary",
|
|
400
400
|
children: [
|
|
401
401
|
_("billing.refunds.footer", "Refund requests are reviewed by our team within 3–5 business days. For urgent issues, contact support."),
|
|
402
402
|
" ",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserRefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/UserRefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - User Refunds Page\n * Shows the user's refund request history and allows submitting new requests.\n */\n\nimport { useState, useEffect, useRef, type FC, type FormEvent } from 'react';\nimport {\n RotateCcw,\n PlusCircle,\n X,\n Clock,\n CheckCircle,\n XCircle,\n Loader2,\n Search,\n CreditCard,\n} from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { formatCurrency, formatDateTime } from '../../../shared/utils';\nimport { PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useGetBillingAccountsCheckoutQuery,\n useGetTransactionLazyQuery,\n useGetRefundRecordsQuery,\n useCreateRefundRecordMutation,\n type GetRefundRecordsQuery,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { RefundRecordStatus } from '../../../../generated/global-types';\n\ntype RefundItem = NonNullable<GetRefundRecordsQuery['getRefundRecords']['records']>[number];\ntype TxnLookup = NonNullable<GetTransactionQuery['getTransaction']>;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// ============================================================================\n// Status helpers\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; className: string; icon: FC<{ className?: string }> }\n> = {\n [RefundRecordStatus.Pending]: {\n label: 'In Review',\n className: 'bg-status-warning-bg/20 text-status-warning-text border-status-warning-border',\n icon: ({ className }) => <Clock className={className} />,\n },\n [RefundRecordStatus.Processing]: {\n label: 'Processing',\n className: 'bg-action-primary-bg/15 text-action-primary-bg border-action-primary-bg/30',\n icon: ({ className }) => <Loader2 className={`${className} animate-spin`} />,\n },\n [RefundRecordStatus.Completed]: {\n label: 'Refunded',\n className: 'bg-status-success-bg/20 text-status-success-text border-status-success-border',\n icon: ({ className }) => <CheckCircle className={className} />,\n },\n [RefundRecordStatus.Failed]: {\n label: 'Failed',\n className: 'bg-status-error-bg/20 text-status-error-text border-status-error-border',\n icon: ({ className }) => <XCircle className={className} />,\n },\n [RefundRecordStatus.Skipped]: {\n label: 'Closed',\n className: 'bg-muted text-muted-foreground border-border',\n icon: ({ className }) => <XCircle className={className} />,\n },\n};\n\nfunction StatusBadge({ status }: { status: string }) {\n const cfg = STATUS_CONFIG[status as RefundRecordStatus] ?? {\n label: status,\n className: 'bg-muted text-muted-foreground border-border',\n icon: ({ className }: { className?: string }) => <Clock className={className} />,\n };\n const Icon = cfg.icon;\n return (\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-xs font-medium ${cfg.className}`}\n >\n <Icon className=\"size-3\" />\n {cfg.label}\n </span>\n );\n}\n\n// ============================================================================\n// Main page\n// ============================================================================\n\nexport const UserRefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const navigateTo = useBillingNavigate();\n\n // Form state\n const [showForm, setShowForm] = useState(false);\n const [txnIdInput, setTxnIdInput] = useState('');\n const [lookedUpTxn, setLookedUpTxn] = useState<TxnLookup | null>(null);\n const [txnNotFound, setTxnNotFound] = useState(false);\n const [reason, setReason] = useState('');\n const [amount, setAmount] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n const [formSuccess, setFormSuccess] = useState(false);\n\n // All billing accounts\n const { data: accountsData, loading: accountsLoading } = useGetBillingAccountsCheckoutQuery({\n fetchPolicy: 'cache-and-network',\n });\n type BillingAccount = NonNullable<typeof accountsData>['getBillingAccountsByOrg'][number];\n const accounts: BillingAccount[] = accountsData?.getBillingAccountsByOrg ?? [];\n\n // Default to the first account; user can switch\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!selectedAccountId && accounts.length > 0) {\n setSelectedAccountId(accounts[0].id);\n }\n }, [accounts, selectedAccountId]);\n\n const selectedAccount = accounts.find((a) => a.id === selectedAccountId);\n\n // Transaction lookup by ID (lazy — fires when user enters a valid UUID)\n const [fetchTxn, { data: txnLookupData, loading: txnLookupLoading, error: txnLookupError }] =\n useGetTransactionLazyQuery({ fetchPolicy: 'network-only' });\n\n // Track the \"active\" lookup key so we only apply results for the latest request\n const lastLookupKey = useRef('');\n\n useEffect(() => {\n if (txnLookupLoading) return;\n const txn = txnLookupData?.getTransaction;\n if (txn) {\n setLookedUpTxn(txn);\n setTxnNotFound(false);\n setAmount(String(txn.amount));\n } else if (txnLookupData !== undefined || txnLookupError) {\n setLookedUpTxn(null);\n setTxnNotFound(true);\n setAmount('');\n }\n }, [txnLookupData, txnLookupLoading, txnLookupError]);\n\n const triggerLookup = (txnId: string, accountId: string) => {\n const key = `${txnId}::${accountId}`;\n lastLookupKey.current = key;\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n fetchTxn({ variables: { id: txnId, billingAccountId: accountId } });\n };\n\n const handleTxnIdChange = (value: string) => {\n setTxnIdInput(value);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(value.trim()) && selectedAccountId) {\n triggerLookup(value.trim(), selectedAccountId);\n }\n };\n\n // When account changes, re-fetch the transaction if one is entered\n const handleAccountChange = (accountId: string) => {\n setSelectedAccountId(accountId);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(txnIdInput.trim())) {\n triggerLookup(txnIdInput.trim(), accountId);\n }\n };\n\n // Refund history for selected account\n const {\n data: refundsData,\n loading: refundsLoading,\n refetch: refetchRefunds,\n } = useGetRefundRecordsQuery({\n variables: { billingAccountId: selectedAccountId, pageSize: 20, page: 1 },\n skip: !selectedAccountId,\n fetchPolicy: 'cache-and-network',\n });\n const refunds = refundsData?.getRefundRecords.records ?? [];\n\n const [createRefund, { loading: isSubmitting }] = useCreateRefundRecordMutation({\n refetchQueries: ['GetRefundRecords'],\n });\n\n const getGatewayInfo = (txn: TxnLookup | null) => {\n if (!txn) return null;\n if (txn.stripePaymentId) return { provider: 'STRIPE', gatewayPaymentId: txn.stripePaymentId };\n if (txn.razorpayPaymentId)\n return { provider: 'RAZORPAY', gatewayPaymentId: txn.razorpayPaymentId };\n return null;\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setFormError(null);\n\n if (!lookedUpTxn || !reason.trim() || !amount) {\n setFormError('Enter a valid transaction ID, an amount, and a reason.');\n return;\n }\n const gatewayInfo = getGatewayInfo(lookedUpTxn);\n if (!gatewayInfo) {\n setFormError('No payment gateway info found for this transaction. Please contact support.');\n return;\n }\n const parsedAmount = parseFloat(amount);\n if (isNaN(parsedAmount) || parsedAmount <= 0) {\n setFormError('Please enter a valid amount greater than 0.');\n return;\n }\n if (parsedAmount > lookedUpTxn.amount) {\n setFormError(\n `Cannot exceed the original payment amount (${formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}).`\n );\n return;\n }\n\n try {\n await createRefund({\n variables: {\n billingAccountId: selectedAccountId,\n provider: gatewayInfo.provider,\n gatewayPaymentId: gatewayInfo.gatewayPaymentId,\n amount: parsedAmount,\n currency: lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD',\n transactionId: lookedUpTxn.id,\n reason: reason.trim(),\n notes: `Requested by user via billing portal`,\n },\n });\n setFormSuccess(true);\n setShowForm(false);\n resetFormFields();\n await refetchRefunds();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to submit refund request.');\n }\n };\n\n const resetFormFields = () => {\n setTxnIdInput('');\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setReason('');\n setAmount('');\n setFormError(null);\n };\n\n const resetForm = () => {\n setShowForm(false);\n setFormSuccess(false);\n resetFormFields();\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refunds')}\n description={tr(\n 'billing.refunds.description',\n 'View your refund requests and submit new ones'\n )}\n actions={\n !showForm ? (\n <button\n type=\"button\"\n onClick={() => {\n setShowForm(true);\n setFormSuccess(false);\n }}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n <PlusCircle className=\"size-4\" />\n {tr('billing.refunds.requestRefund', 'Request Refund')}\n </button>\n ) : undefined\n }\n />\n\n {/* Billing account switcher */}\n {!accountsLoading && accounts.length > 1 && (\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"size-4 text-muted-foreground shrink-0\" />\n <label htmlFor=\"accountSwitch\" className=\"text-sm text-muted-foreground shrink-0\">\n {tr('billing.refunds.account', 'Billing account')}\n </label>\n <select\n id=\"accountSwitch\"\n value={selectedAccountId ?? ''}\n onChange={(e) => handleAccountChange(e.target.value)}\n className=\"flex-1 px-3 py-1.5 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary text-sm\"\n >\n {accounts.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.currency}) — {a.email}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Success banner */}\n {formSuccess && (\n <div className=\"flex items-center justify-between p-4 rounded-lg border border-status-success-border bg-status-success-bg/10\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-4 text-status-success-text\" />\n <p className=\"text-sm text-status-success-text font-medium\">\n {tr(\n 'billing.refunds.submitted',\n 'Refund request submitted. Our team will review it shortly.'\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => setFormSuccess(false)}\n className=\"text-status-success-text hover:opacity-70\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n )}\n\n {/* Request Refund Form */}\n {showForm && (\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"flex items-center justify-between p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">\n {tr('billing.refunds.newRequest', 'New Refund Request')}\n </h2>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"p-1 rounded hover:bg-muted transition-colors\"\n >\n <X className=\"size-4 text-muted-foreground\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {formError && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg/10\">\n <p className=\"text-sm text-status-error-text\">{formError}</p>\n </div>\n )}\n\n {/* Transaction ID lookup */}\n <div>\n <label htmlFor=\"txnId\" className=\"block text-sm font-medium text-foreground mb-1\">\n {tr('billing.refunds.transactionId', 'Transaction ID')} *\n </label>\n <div className=\"relative\">\n <input\n id=\"txnId\"\n type=\"text\"\n value={txnIdInput}\n onChange={(e) => handleTxnIdChange(e.target.value)}\n placeholder=\"Paste your transaction ID...\"\n className=\"w-full pl-3 pr-9 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary text-sm font-mono\"\n />\n <div className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-muted-foreground\">\n {txnLookupLoading ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n </div>\n </div>\n\n {/* Transaction lookup result */}\n {lookedUpTxn && (\n <div className=\"mt-2 p-3 rounded-md border border-status-success-border bg-status-success-bg/10 text-sm space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-3.5 text-status-success-text shrink-0\" />\n <span className=\"font-medium text-foreground\">\n {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n <span className=\"text-muted-foreground\">·</span>\n <span className=\"text-muted-foreground\">\n {formatDateTime(lookedUpTxn.createdAt)}\n </span>\n {lookedUpTxn.stripePaymentId && (\n <span className=\"text-xs text-muted-foreground\">Stripe</span>\n )}\n {lookedUpTxn.razorpayPaymentId && (\n <span className=\"text-xs text-muted-foreground\">Razorpay</span>\n )}\n </div>\n {lookedUpTxn.description && (\n <p className=\"text-xs text-muted-foreground pl-5\">{lookedUpTxn.description}</p>\n )}\n </div>\n )}\n {txnNotFound && txnIdInput.length > 0 && !txnLookupLoading && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr(\n 'billing.refunds.txnNotFound',\n 'Transaction not found in this billing account.'\n )}\n </p>\n )}\n {!UUID_RE.test(txnIdInput.trim()) && txnIdInput.length > 4 && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {tr(\n 'billing.refunds.txnIdHint',\n 'Transaction IDs look like: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n )}\n </p>\n )}\n </div>\n\n {/* Amount — only shown once transaction is found */}\n {lookedUpTxn && (\n <div>\n <label\n htmlFor=\"refundAmount\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n {tr('billing.refunds.amount', 'Refund Amount')} *\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n id=\"refundAmount\"\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={lookedUpTxn.amount}\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n required\n className=\"w-40 px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary text-sm\"\n placeholder=\"0.00\"\n />\n <span className=\"text-sm text-muted-foreground\">\n {lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD'}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n max {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n </div>\n </div>\n )}\n\n {/* Reason */}\n <div>\n <label htmlFor=\"reason\" className=\"block text-sm font-medium text-foreground mb-1\">\n {tr('billing.refunds.reason', 'Reason for refund')} *\n </label>\n <textarea\n id=\"reason\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n required\n rows={3}\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 text-sm resize-none\"\n placeholder={tr(\n 'billing.refunds.reasonPlaceholder',\n 'Describe why you are requesting a refund...'\n )}\n />\n </div>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !lookedUpTxn || !reason.trim() || !amount}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting\n ? tr('billing.refunds.submitting', 'Submitting...')\n : tr('billing.refunds.submitRequest', 'Submit Request')}\n </button>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"px-4 py-2 text-sm border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n {tr('billing.common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n </div>\n )}\n\n {/* Refund history */}\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\">\n {tr('billing.refunds.history', 'Refund History')}\n </h2>\n </div>\n\n {accountsLoading || refundsLoading ? (\n <div className=\"p-8 flex items-center justify-center\">\n <Loader2 className=\"size-5 animate-spin text-muted-foreground\" />\n </div>\n ) : refunds.length === 0 ? (\n <div className=\"p-10 flex flex-col items-center text-center gap-3\">\n <RotateCcw className=\"size-8 text-muted-foreground\" />\n <p className=\"text-sm font-medium text-foreground\">\n {tr('billing.refunds.noRefunds', 'No refund requests yet')}\n </p>\n <p className=\"text-xs text-muted-foreground max-w-sm\">\n {tr(\n 'billing.refunds.noRefundsHint',\n 'If you have an issue with a payment, click \"Request Refund\" to get started.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"divide-y divide-border\">\n {refunds.map((r: RefundItem) => (\n <li\n key={r.id}\n className=\"flex items-start gap-4 p-4 hover:bg-muted/30 transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium text-foreground\">\n {formatCurrency(r.amount, r.currency)}\n </span>\n <StatusBadge status={r.status} />\n {r.purchaseDetail && (\n <span className=\"text-xs text-muted-foreground truncate\">\n {r.purchaseDetail}\n </span>\n )}\n </div>\n {r.reason && (\n <p className=\"text-xs text-muted-foreground mt-1 line-clamp-2\">{r.reason}</p>\n )}\n {r.errorMessage && r.status === RefundRecordStatus.Failed && (\n <p className=\"text-xs text-status-error-text mt-1\">{r.errorMessage}</p>\n )}\n </div>\n <div className=\"text-right shrink-0\">\n <p className=\"text-xs text-muted-foreground\">{formatDateTime(r.createdAt)}</p>\n {r.processedAt && (\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n Processed {formatDateTime(r.processedAt)}\n </p>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n <p className=\"text-xs text-muted-foreground\">\n {tr(\n 'billing.refunds.footer',\n 'Refund requests are reviewed by our team within 3–5 business days. For urgent issues, contact support.'\n )}{' '}\n <button\n type=\"button\"\n onClick={() => navigateTo('/transactions/' + selectedAccountId)}\n className=\"underline hover:no-underline\"\n >\n {tr('billing.refunds.viewTransactions', 'View all transactions')}\n </button>\n </p>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAkCA,IAAM,IAAU,mEAMV,IAGF;EACD,EAAmB,UAAU;EAC5B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAkB,cAAa,CAAA;EACzD;EACA,EAAmB,aAAa;EAC/B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAS,WAAW,GAAG,EAAU,gBAAkB,CAAA;EAC7E;EACA,EAAmB,YAAY;EAC9B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAwB,cAAa,CAAA;EAC/D;EACA,EAAmB,SAAS;EAC3B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAoB,cAAa,CAAA;EAC3D;EACA,EAAmB,UAAU;EAC5B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAoB,cAAa,CAAA;EAC3D;CACF;AAED,SAAS,GAAY,EAAE,aAA8B;CACnD,IAAM,IAAM,EAAc,MAAiC;EACzD,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAwC,kBAAC,GAAD,EAAkB,cAAa,CAAA;EACjF,EACK,IAAO,EAAI;AACjB,QACE,kBAAC,QAAD;EACE,WAAW,sFAAsF,EAAI;YADvG,CAGE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EAAI,MACA;;;AAQX,IAAa,UAA4B;CACvC,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;IAE1B,IAAa,GAAoB,EAGjC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAa,KAAkB,EAA2B,KAAK,EAChE,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,IAAa,KAAkB,EAAS,GAAM,EAG/C,EAAE,MAAM,IAAc,SAAS,MAAoB,EAAmC,EAC1F,aAAa,qBACd,CAAC,EAEI,IAA6B,IAAc,2BAA2B,EAAE,EAGxE,CAAC,GAAmB,KAAwB,EAA6B,KAAA,EAAU;AACzF,SAAgB;AACd,EAAI,CAAC,KAAqB,EAAS,SAAS,KAC1C,EAAqB,EAAS,GAAG,GAAG;IAErC,CAAC,GAAU,EAAkB,CAAC;CAEjC,IAAM,IAAkB,EAAS,MAAM,MAAM,EAAE,OAAO,EAAkB,EAGlE,CAAC,GAAU,EAAE,MAAM,GAAe,SAAS,GAAkB,OAAO,OACxE,EAA2B,EAAE,aAAa,gBAAgB,CAAC,EAGvD,IAAgB,EAAO,GAAG;AAEhC,SAAgB;AACd,MAAI,EAAkB;EACtB,IAAM,IAAM,GAAe;AAC3B,EAAI,KACF,EAAe,EAAI,EACnB,EAAe,GAAM,EACrB,EAAU,OAAO,EAAI,OAAO,CAAC,KACpB,MAAkB,KAAA,KAAa,OACxC,EAAe,KAAK,EACpB,EAAe,GAAK,EACpB,EAAU,GAAG;IAEd;EAAC;EAAe;EAAkB;EAAe,CAAC;CAErD,IAAM,KAAiB,GAAe,MAAsB;AAM1D,EAJA,EAAc,UADF,GAAG,EAAM,IAAI,KAEzB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACb,EAAS,EAAE,WAAW;GAAE,IAAI;GAAO,kBAAkB;GAAW,EAAE,CAAC;IAG/D,MAAqB,MAAkB;AAK3C,EAJA,EAAc,EAAM,EACpB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACT,EAAQ,KAAK,EAAM,MAAM,CAAC,IAAI,KAChC,EAAc,EAAM,MAAM,EAAE,EAAkB;IAK5C,MAAuB,MAAsB;AAKjD,EAJA,EAAqB,EAAU,EAC/B,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACT,EAAQ,KAAK,EAAW,MAAM,CAAC,IACjC,EAAc,EAAW,MAAM,EAAE,EAAU;IAKzC,EACJ,MAAM,IACN,SAAS,IACT,SAAS,OACP,EAAyB;EAC3B,WAAW;GAAE,kBAAkB;GAAmB,UAAU;GAAI,MAAM;GAAG;EACzE,MAAM,CAAC;EACP,aAAa;EACd,CAAC,EACI,IAAU,IAAa,iBAAiB,WAAW,EAAE,EAErD,CAAC,IAAc,EAAE,SAAS,OAAkB,EAA8B,EAC9E,gBAAgB,CAAC,mBAAmB,EACrC,CAAC,EAEI,KAAkB,MACjB,IACD,EAAI,kBAAwB;EAAE,UAAU;EAAU,kBAAkB,EAAI;EAAiB,GACzF,EAAI,oBACC;EAAE,UAAU;EAAY,kBAAkB,EAAI;EAAmB,GACnE,OAJU,MAOb,KAAe,OAAO,MAAiB;AAI3C,MAHA,EAAE,gBAAgB,EAClB,EAAa,KAAK,EAEd,CAAC,KAAe,CAAC,EAAO,MAAM,IAAI,CAAC,GAAQ;AAC7C,KAAa,yDAAyD;AACtE;;EAEF,IAAM,IAAc,EAAe,EAAY;AAC/C,MAAI,CAAC,GAAa;AAChB,KAAa,8EAA8E;AAC3F;;EAEF,IAAM,IAAe,WAAW,EAAO;AACvC,MAAI,MAAM,EAAa,IAAI,KAAgB,GAAG;AAC5C,KAAa,8CAA8C;AAC3D;;AAEF,MAAI,IAAe,EAAY,QAAQ;AACrC,KACE,8CAA8C,EAAe,EAAY,QAAQ,EAAY,SAAS,CAAC,IACxG;AACD;;AAGF,MAAI;AAgBF,GAfA,MAAM,GAAa,EACjB,WAAW;IACT,kBAAkB;IAClB,UAAU,EAAY;IACtB,kBAAkB,EAAY;IAC9B,QAAQ;IACR,UAAU,EAAY,YAAY,GAAiB,YAAY;IAC/D,eAAe,EAAY;IAC3B,QAAQ,EAAO,MAAM;IACrB,OAAO;IACR,EACF,CAAC,EACF,EAAe,GAAK,EACpB,EAAY,GAAM,EAClB,GAAiB,EACjB,MAAM,IAAgB;WACf,GAAK;AACZ,KAAa,aAAe,QAAQ,EAAI,UAAU,mCAAmC;;IAInF,UAAwB;AAM5B,EALA,EAAc,GAAG,EACjB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACb,EAAU,GAAG,EACb,EAAa,KAAK;IAGd,UAAkB;AAGtB,EAFA,EAAY,GAAM,EAClB,EAAe,GAAM,EACrB,GAAiB;;AAGnB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,UAAU;IAC7C,aAAa,EACX,+BACA,gDACD;IACD,SACG,IAYG,KAAA,IAXF,kBAAC,UAAD;KACE,MAAK;KACL,eAAe;AAEb,MADA,EAAY,GAAK,EACjB,EAAe,GAAM;;KAEvB,WAAU;eANZ,CAQE,kBAAC,IAAD,EAAY,WAAU,UAAW,CAAA,EAChC,EAAG,iCAAiC,iBAAiB,CAC/C;;IAGb,CAAA;GAGD,CAAC,KAAmB,EAAS,SAAS,KACrC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAY,WAAU,yCAA0C,CAAA;KAChE,kBAAC,SAAD;MAAO,SAAQ;MAAgB,WAAU;gBACtC,EAAG,2BAA2B,kBAAkB;MAC3C,CAAA;KACR,kBAAC,UAAD;MACE,IAAG;MACH,OAAO,KAAqB;MAC5B,WAAW,MAAM,GAAoB,EAAE,OAAO,MAAM;MACpD,WAAU;gBAET,EAAS,KAAK,MACb,kBAAC,UAAD;OAAmB,OAAO,EAAE;iBAA5B;QACG,EAAE;QAAK;QAAG,EAAE;QAAS;QAAK,EAAE;QACtB;SAFI,EAAE,GAEN,CACT;MACK,CAAA;KACL;;GAIP,MACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAa,WAAU,mCAAoC,CAAA,EAC3D,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,6BACA,6DACD;MACC,CAAA,CACA;QACN,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAe,GAAM;KACpC,WAAU;eAEV,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;KACjB,CAAA,CACL;;GAIP,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,8BAA8B,qBAAqB;MACpD,CAAA,EACL,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAEV,kBAAC,GAAD,EAAG,WAAU,gCAAiC,CAAA;MACvC,CAAA,CACL;QAEN,kBAAC,QAAD;KAAM,UAAU;KAAc,WAAU;eAAxC;MACG,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBAAkC;QAAc,CAAA;OACzD,CAAA;MAIR,kBAAC,OAAD,EAAA,UAAA;OACE,kBAAC,SAAD;QAAO,SAAQ;QAAQ,WAAU;kBAAjC,CACG,EAAG,iCAAiC,iBAAiB,EAAC,KACjD;;OACR,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,OAAO;SACP,WAAW,MAAM,GAAkB,EAAE,OAAO,MAAM;SAClD,aAAY;SACZ,WAAU;SACV,CAAA,EACF,kBAAC,OAAD;SAAK,WAAU;mBACZ,IACC,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,GAE3C,kBAAC,IAAD,EAAQ,WAAU,UAAW,CAAA;SAE3B,CAAA,CACF;;OAGL,KACC,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,GAAD,EAAa,WAAU,8CAA+C,CAAA;UACtE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAY,QAAQ,EAAY,SAAS;WACpD,CAAA;UACP,kBAAC,QAAD;WAAM,WAAU;qBAAwB;WAAQ,CAAA;UAChD,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAY,UAAU;WACjC,CAAA;UACN,EAAY,mBACX,kBAAC,QAAD;WAAM,WAAU;qBAAgC;WAAa,CAAA;UAE9D,EAAY,qBACX,kBAAC,QAAD;WAAM,WAAU;qBAAgC;WAAe,CAAA;UAE7D;YACL,EAAY,eACX,kBAAC,KAAD;SAAG,WAAU;mBAAsC,EAAY;SAAgB,CAAA,CAE7E;;OAEP,KAAe,EAAW,SAAS,KAAK,CAAC,KACxC,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,+BACA,iDACD;QACC,CAAA;OAEL,CAAC,EAAQ,KAAK,EAAW,MAAM,CAAC,IAAI,EAAW,SAAS,KACvD,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,6BACA,kEACD;QACC,CAAA;OAEF,EAAA,CAAA;MAGL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OACE,SAAQ;OACR,WAAU;iBAFZ,CAIG,EAAG,0BAA0B,gBAAgB,EAAC,KACzC;UACR,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,MAAK;SACL,KAAI;SACJ,KAAK,EAAY;SACjB,OAAO;SACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;SAC1C,UAAA;SACA,WAAU;SACV,aAAY;SACZ,CAAA;QACF,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAY,YAAY,GAAiB,YAAY;SACjD,CAAA;QACP,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAAgD,QACzC,EAAe,EAAY,QAAQ,EAAY,SAAS,CACxD;;QACH;SACF,EAAA,CAAA;MAIR,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAS,WAAU;iBAAlC,CACG,EAAG,0BAA0B,oBAAoB,EAAC,KAC7C;UACR,kBAAC,YAAD;OACE,IAAG;OACH,OAAO;OACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;OAC1C,UAAA;OACA,MAAM;OACN,WAAU;OACV,aAAa,EACX,qCACA,8CACD;OACD,CAAA,CACE,EAAA,CAAA;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,UAAD;QACE,MAAK;QACL,UAAU,KAAgB,CAAC,KAAe,CAAC,EAAO,MAAM,IAAI,CAAC;QAC7D,WAAU;kBAET,IACG,EAAG,8BAA8B,gBAAgB,GACjD,EAAG,iCAAiC,iBAAiB;QAClD,CAAA,EACT,kBAAC,UAAD;QACE,MAAK;QACL,SAAS;QACT,WAAU;kBAET,EAAG,yBAAyB,SAAS;QAC/B,CAAA,CACL;;MACD;OACH;;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,2BAA2B,iBAAiB;MAC7C,CAAA;KACD,CAAA,EAEL,KAAmB,KAClB,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAS,WAAU,6CAA8C,CAAA;KAC7D,CAAA,GACJ,EAAQ,WAAW,IACrB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,IAAD,EAAW,WAAU,gCAAiC,CAAA;MACtD,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAG,6BAA6B,yBAAyB;OACxD,CAAA;MACJ,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,iCACA,gFACD;OACC,CAAA;MACA;SAEN,kBAAC,MAAD;KAAI,WAAU;eACX,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAE,QAAQ,EAAE,SAAS;WAChC,CAAA;UACP,kBAAC,IAAD,EAAa,QAAQ,EAAE,QAAU,CAAA;UAChC,EAAE,kBACD,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAE;WACE,CAAA;UAEL;;QACL,EAAE,UACD,kBAAC,KAAD;SAAG,WAAU;mBAAmD,EAAE;SAAW,CAAA;QAE9E,EAAE,gBAAgB,EAAE,WAAW,EAAmB,UACjD,kBAAC,KAAD;SAAG,WAAU;mBAAuC,EAAE;SAAiB,CAAA;QAErE;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAAiC,EAAe,EAAE,UAAU;QAAK,CAAA,EAC7E,EAAE,eACD,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAAoD,cACvC,EAAe,EAAE,YAAY,CACtC;UAEF;SACH;QA9BE,EAAE,GA8BJ,CACL;KACC,CAAA,CAEH;;GAEN,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EACC,0BACA,yGACD;KAAE;KACH,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAW,mBAAmB,EAAkB;MAC/D,WAAU;gBAET,EAAG,oCAAoC,wBAAwB;MACzD,CAAA;KACP;;GACA"}
|
|
1
|
+
{"version":3,"file":"UserRefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/UserRefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - User Refunds Page\n * Shows the user's refund request history and allows submitting new requests.\n */\n\nimport { useState, useEffect, useRef, type FC, type FormEvent } from 'react';\nimport {\n RotateCcw,\n PlusCircle,\n X,\n Clock,\n CheckCircle,\n XCircle,\n Loader2,\n Search,\n CreditCard,\n} from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { formatCurrency, formatDateTime } from '../../../shared/utils';\nimport { PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useGetBillingAccountsCheckoutQuery,\n useGetTransactionLazyQuery,\n useGetRefundRecordsQuery,\n useCreateRefundRecordMutation,\n type GetRefundRecordsQuery,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { RefundRecordStatus } from '../../../../generated/global-types';\n\ntype RefundItem = NonNullable<GetRefundRecordsQuery['getRefundRecords']['records']>[number];\ntype TxnLookup = NonNullable<GetTransactionQuery['getTransaction']>;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// ============================================================================\n// Status helpers\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; className: string; icon: FC<{ className?: string }> }\n> = {\n [RefundRecordStatus.Pending]: {\n label: 'In Review',\n className: 'bg-status-warning-bg/20 text-status-warning-text border-status-warning-border',\n icon: ({ className }) => <Clock className={className} />,\n },\n [RefundRecordStatus.Processing]: {\n label: 'Processing',\n className: 'bg-action-primary-bg/15 text-action-primary-bg border-action-primary-bg/30',\n icon: ({ className }) => <Loader2 className={`${className} animate-spin`} />,\n },\n [RefundRecordStatus.Completed]: {\n label: 'Refunded',\n className: 'bg-status-success-bg/20 text-status-success-text border-status-success-border',\n icon: ({ className }) => <CheckCircle className={className} />,\n },\n [RefundRecordStatus.Failed]: {\n label: 'Failed',\n className: 'bg-status-error-bg/20 text-status-error-text border-status-error-border',\n icon: ({ className }) => <XCircle className={className} />,\n },\n [RefundRecordStatus.Skipped]: {\n label: 'Closed',\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }) => <XCircle className={className} />,\n },\n};\n\nfunction StatusBadge({ status }: { status: string }) {\n const cfg = STATUS_CONFIG[status as RefundRecordStatus] ?? {\n label: status,\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }: { className?: string }) => <Clock className={className} />,\n };\n const Icon = cfg.icon;\n return (\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-xs font-medium ${cfg.className}`}\n >\n <Icon className=\"size-3\" />\n {cfg.label}\n </span>\n );\n}\n\n// ============================================================================\n// Main page\n// ============================================================================\n\nexport const UserRefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const navigateTo = useBillingNavigate();\n\n // Form state\n const [showForm, setShowForm] = useState(false);\n const [txnIdInput, setTxnIdInput] = useState('');\n const [lookedUpTxn, setLookedUpTxn] = useState<TxnLookup | null>(null);\n const [txnNotFound, setTxnNotFound] = useState(false);\n const [reason, setReason] = useState('');\n const [amount, setAmount] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n const [formSuccess, setFormSuccess] = useState(false);\n\n // All billing accounts\n const { data: accountsData, loading: accountsLoading } = useGetBillingAccountsCheckoutQuery({\n fetchPolicy: 'cache-and-network',\n });\n type BillingAccount = NonNullable<typeof accountsData>['getBillingAccountsByOrg'][number];\n const accounts: BillingAccount[] = accountsData?.getBillingAccountsByOrg ?? [];\n\n // Default to the first account; user can switch\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!selectedAccountId && accounts.length > 0) {\n setSelectedAccountId(accounts[0].id);\n }\n }, [accounts, selectedAccountId]);\n\n const selectedAccount = accounts.find((a) => a.id === selectedAccountId);\n\n // Transaction lookup by ID (lazy — fires when user enters a valid UUID)\n const [fetchTxn, { data: txnLookupData, loading: txnLookupLoading, error: txnLookupError }] =\n useGetTransactionLazyQuery({ fetchPolicy: 'network-only' });\n\n // Track the \"active\" lookup key so we only apply results for the latest request\n const lastLookupKey = useRef('');\n\n useEffect(() => {\n if (txnLookupLoading) return;\n const txn = txnLookupData?.getTransaction;\n if (txn) {\n setLookedUpTxn(txn);\n setTxnNotFound(false);\n setAmount(String(txn.amount));\n } else if (txnLookupData !== undefined || txnLookupError) {\n setLookedUpTxn(null);\n setTxnNotFound(true);\n setAmount('');\n }\n }, [txnLookupData, txnLookupLoading, txnLookupError]);\n\n const triggerLookup = (txnId: string, accountId: string) => {\n const key = `${txnId}::${accountId}`;\n lastLookupKey.current = key;\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n fetchTxn({ variables: { id: txnId, billingAccountId: accountId } });\n };\n\n const handleTxnIdChange = (value: string) => {\n setTxnIdInput(value);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(value.trim()) && selectedAccountId) {\n triggerLookup(value.trim(), selectedAccountId);\n }\n };\n\n // When account changes, re-fetch the transaction if one is entered\n const handleAccountChange = (accountId: string) => {\n setSelectedAccountId(accountId);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(txnIdInput.trim())) {\n triggerLookup(txnIdInput.trim(), accountId);\n }\n };\n\n // Refund history for selected account\n const {\n data: refundsData,\n loading: refundsLoading,\n refetch: refetchRefunds,\n } = useGetRefundRecordsQuery({\n variables: { billingAccountId: selectedAccountId, pageSize: 20, page: 1 },\n skip: !selectedAccountId,\n fetchPolicy: 'cache-and-network',\n });\n const refunds = refundsData?.getRefundRecords.records ?? [];\n\n const [createRefund, { loading: isSubmitting }] = useCreateRefundRecordMutation({\n refetchQueries: ['GetRefundRecords'],\n });\n\n const getGatewayInfo = (txn: TxnLookup | null) => {\n if (!txn) return null;\n if (txn.stripePaymentId) return { provider: 'STRIPE', gatewayPaymentId: txn.stripePaymentId };\n if (txn.razorpayPaymentId)\n return { provider: 'RAZORPAY', gatewayPaymentId: txn.razorpayPaymentId };\n return null;\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setFormError(null);\n\n if (!lookedUpTxn || !reason.trim() || !amount) {\n setFormError('Enter a valid transaction ID, an amount, and a reason.');\n return;\n }\n const gatewayInfo = getGatewayInfo(lookedUpTxn);\n if (!gatewayInfo) {\n setFormError('No payment gateway info found for this transaction. Please contact support.');\n return;\n }\n const parsedAmount = parseFloat(amount);\n if (isNaN(parsedAmount) || parsedAmount <= 0) {\n setFormError('Please enter a valid amount greater than 0.');\n return;\n }\n if (parsedAmount > lookedUpTxn.amount) {\n setFormError(\n `Cannot exceed the original payment amount (${formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}).`\n );\n return;\n }\n\n try {\n await createRefund({\n variables: {\n billingAccountId: selectedAccountId,\n provider: gatewayInfo.provider,\n gatewayPaymentId: gatewayInfo.gatewayPaymentId,\n amount: parsedAmount,\n currency: lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD',\n transactionId: lookedUpTxn.id,\n reason: reason.trim(),\n notes: `Requested by user via billing portal`,\n },\n });\n setFormSuccess(true);\n setShowForm(false);\n resetFormFields();\n await refetchRefunds();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to submit refund request.');\n }\n };\n\n const resetFormFields = () => {\n setTxnIdInput('');\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setReason('');\n setAmount('');\n setFormError(null);\n };\n\n const resetForm = () => {\n setShowForm(false);\n setFormSuccess(false);\n resetFormFields();\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refunds')}\n description={tr(\n 'billing.refunds.description',\n 'View your refund requests and submit new ones'\n )}\n actions={\n !showForm ? (\n <button\n type=\"button\"\n onClick={() => {\n setShowForm(true);\n setFormSuccess(false);\n }}\n className=\"inline-flex items-center gap-2 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\"\n >\n <PlusCircle className=\"size-4\" />\n {tr('billing.refunds.requestRefund', 'Request Refund')}\n </button>\n ) : undefined\n }\n />\n\n {/* Billing account switcher */}\n {!accountsLoading && accounts.length > 1 && (\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"size-4 text-text-secondary shrink-0\" />\n <label htmlFor=\"accountSwitch\" className=\"text-sm text-text-secondary shrink-0\">\n {tr('billing.refunds.account', 'Billing account')}\n </label>\n <select\n id=\"accountSwitch\"\n value={selectedAccountId ?? ''}\n onChange={(e) => handleAccountChange(e.target.value)}\n className=\"flex-1 px-3 py-1.5 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n >\n {accounts.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.currency}) — {a.email}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Success banner */}\n {formSuccess && (\n <div className=\"flex items-center justify-between p-4 rounded-lg border border-status-success-border bg-status-success-bg/10\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-4 text-status-success-text\" />\n <p className=\"text-sm text-status-success-text font-medium\">\n {tr(\n 'billing.refunds.submitted',\n 'Refund request submitted. Our team will review it shortly.'\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => setFormSuccess(false)}\n className=\"text-status-success-text hover:opacity-70\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n )}\n\n {/* Request Refund Form */}\n {showForm && (\n <div className=\"border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.newRequest', 'New Refund Request')}\n </h2>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-4 text-text-secondary\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {formError && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg/10\">\n <p className=\"text-sm text-status-error-text\">{formError}</p>\n </div>\n )}\n\n {/* Transaction ID lookup */}\n <div>\n <label htmlFor=\"txnId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.transactionId', 'Transaction ID')} *\n </label>\n <div className=\"relative\">\n <input\n id=\"txnId\"\n type=\"text\"\n value={txnIdInput}\n onChange={(e) => handleTxnIdChange(e.target.value)}\n placeholder=\"Paste your transaction ID...\"\n className=\"w-full pl-3 pr-9 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm font-mono\"\n />\n <div className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-text-secondary\">\n {txnLookupLoading ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n </div>\n </div>\n\n {/* Transaction lookup result */}\n {lookedUpTxn && (\n <div className=\"mt-2 p-3 rounded-button border border-status-success-border bg-status-success-bg/10 text-sm space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-3.5 text-status-success-text shrink-0\" />\n <span className=\"font-medium text-text-primary\">\n {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n <span className=\"text-text-secondary\">·</span>\n <span className=\"text-text-secondary\">\n {formatDateTime(lookedUpTxn.createdAt)}\n </span>\n {lookedUpTxn.stripePaymentId && (\n <span className=\"text-xs text-text-secondary\">Stripe</span>\n )}\n {lookedUpTxn.razorpayPaymentId && (\n <span className=\"text-xs text-text-secondary\">Razorpay</span>\n )}\n </div>\n {lookedUpTxn.description && (\n <p className=\"text-xs text-text-secondary pl-5\">{lookedUpTxn.description}</p>\n )}\n </div>\n )}\n {txnNotFound && txnIdInput.length > 0 && !txnLookupLoading && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr(\n 'billing.refunds.txnNotFound',\n 'Transaction not found in this billing account.'\n )}\n </p>\n )}\n {!UUID_RE.test(txnIdInput.trim()) && txnIdInput.length > 4 && (\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.txnIdHint',\n 'Transaction IDs look like: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n )}\n </p>\n )}\n </div>\n\n {/* Amount — only shown once transaction is found */}\n {lookedUpTxn && (\n <div>\n <label\n htmlFor=\"refundAmount\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('billing.refunds.amount', 'Refund Amount')} *\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n id=\"refundAmount\"\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={lookedUpTxn.amount}\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n required\n className=\"w-40 px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n placeholder=\"0.00\"\n />\n <span className=\"text-sm text-text-secondary\">\n {lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD'}\n </span>\n <span className=\"text-xs text-text-secondary\">\n max {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n </div>\n </div>\n )}\n\n {/* Reason */}\n <div>\n <label htmlFor=\"reason\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.reason', 'Reason for refund')} *\n </label>\n <textarea\n id=\"reason\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n required\n rows={3}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm resize-none\"\n placeholder={tr(\n 'billing.refunds.reasonPlaceholder',\n 'Describe why you are requesting a refund...'\n )}\n />\n </div>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !lookedUpTxn || !reason.trim() || !amount}\n 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 disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting\n ? tr('billing.refunds.submitting', 'Submitting...')\n : tr('billing.refunds.submitRequest', 'Submit Request')}\n </button>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"px-4 py-2 text-sm border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors\"\n >\n {tr('billing.common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n </div>\n )}\n\n {/* Refund history */}\n <div className=\"border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.history', 'Refund History')}\n </h2>\n </div>\n\n {accountsLoading || refundsLoading ? (\n <div className=\"p-8 flex items-center justify-center\">\n <Loader2 className=\"size-5 animate-spin text-text-secondary\" />\n </div>\n ) : refunds.length === 0 ? (\n <div className=\"p-10 flex flex-col items-center text-center gap-3\">\n <RotateCcw className=\"size-8 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('billing.refunds.noRefunds', 'No refund requests yet')}\n </p>\n <p className=\"text-xs text-text-secondary max-w-sm\">\n {tr(\n 'billing.refunds.noRefundsHint',\n 'If you have an issue with a payment, click \"Request Refund\" to get started.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"divide-y divide-border-subtle\">\n {refunds.map((r: RefundItem) => (\n <li\n key={r.id}\n className=\"flex items-start gap-4 p-4 hover:bg-bg-sunken transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(r.amount, r.currency)}\n </span>\n <StatusBadge status={r.status} />\n {r.purchaseDetail && (\n <span className=\"text-xs text-text-secondary truncate\">\n {r.purchaseDetail}\n </span>\n )}\n </div>\n {r.reason && (\n <p className=\"text-xs text-text-secondary mt-1 line-clamp-2\">{r.reason}</p>\n )}\n {r.errorMessage && r.status === RefundRecordStatus.Failed && (\n <p className=\"text-xs text-status-error-text mt-1\">{r.errorMessage}</p>\n )}\n </div>\n <div className=\"text-right shrink-0\">\n <p className=\"text-xs text-text-secondary\">{formatDateTime(r.createdAt)}</p>\n {r.processedAt && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Processed {formatDateTime(r.processedAt)}\n </p>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.footer',\n 'Refund requests are reviewed by our team within 3–5 business days. For urgent issues, contact support.'\n )}{' '}\n <button\n type=\"button\"\n onClick={() => navigateTo('/transactions/' + selectedAccountId)}\n className=\"underline hover:no-underline\"\n >\n {tr('billing.refunds.viewTransactions', 'View all transactions')}\n </button>\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -23,11 +23,11 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
23
23
|
let C = f.find((e) => e.id === p);
|
|
24
24
|
return h ? /* @__PURE__ */ u("div", {
|
|
25
25
|
className: "space-y-2",
|
|
26
|
-
children: [/* @__PURE__ */ l("div", { className: "h-4 w-28 bg-
|
|
26
|
+
children: [/* @__PURE__ */ l("div", { className: "h-4 w-28 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ l("div", { className: "h-12 bg-bg-sunken animate-pulse rounded-lg" })]
|
|
27
27
|
}) : f.length === 0 ? /* @__PURE__ */ u("div", {
|
|
28
|
-
className: "rounded-lg border border-dashed border-border p-4 text-center",
|
|
29
|
-
children: [/* @__PURE__ */ l(i, { className: "mx-auto size-6 text-
|
|
30
|
-
className: "mt-2 text-sm text-
|
|
28
|
+
className: "rounded-lg border border-dashed border-border-subtle p-4 text-center",
|
|
29
|
+
children: [/* @__PURE__ */ l(i, { className: "mx-auto size-6 text-text-secondary" }), /* @__PURE__ */ l("p", {
|
|
30
|
+
className: "mt-2 text-sm text-text-secondary",
|
|
31
31
|
children: "No billing accounts found"
|
|
32
32
|
})]
|
|
33
33
|
}) : /* @__PURE__ */ u("div", {
|
|
@@ -37,10 +37,10 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
37
37
|
/* @__PURE__ */ u("div", {
|
|
38
38
|
className: "flex items-center justify-between",
|
|
39
39
|
children: [/* @__PURE__ */ l("label", {
|
|
40
|
-
className: "text-sm font-medium text-
|
|
40
|
+
className: "text-sm font-medium text-text-primary",
|
|
41
41
|
children: y("billing.checkout.billingAccount", "Billing Account")
|
|
42
42
|
}), g && /* @__PURE__ */ u("span", {
|
|
43
|
-
className: "flex items-center gap-1 text-xs text-
|
|
43
|
+
className: "flex items-center gap-1 text-xs text-text-secondary",
|
|
44
44
|
children: [/* @__PURE__ */ l(c, { className: "size-3" }), "Locked"]
|
|
45
45
|
})]
|
|
46
46
|
}),
|
|
@@ -51,13 +51,13 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
51
51
|
className: `
|
|
52
52
|
w-full flex items-center justify-between gap-3 p-3 rounded-lg border
|
|
53
53
|
transition-colors text-left
|
|
54
|
-
${g ? "border-border bg-
|
|
54
|
+
${g ? "border-border-subtle bg-bg-sunken cursor-not-allowed opacity-80" : b ? "border-border-strong ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle hover:border-border-strong"}
|
|
55
55
|
`,
|
|
56
56
|
children: [C ? /* @__PURE__ */ u("div", {
|
|
57
57
|
className: "flex items-center gap-3 min-w-0 flex-1",
|
|
58
58
|
children: [
|
|
59
59
|
/* @__PURE__ */ l("div", {
|
|
60
|
-
className: `flex size-8 shrink-0 items-center justify-center rounded-full ${g ? "bg-
|
|
60
|
+
className: `flex size-8 shrink-0 items-center justify-center rounded-full ${g ? "bg-bg-sunken text-text-secondary" : "bg-[var(--color-accent-soft)] text-text-link"}`,
|
|
61
61
|
children: /* @__PURE__ */ l(i, { className: "size-4" })
|
|
62
62
|
}),
|
|
63
63
|
/* @__PURE__ */ u("div", {
|
|
@@ -65,36 +65,36 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
65
65
|
children: [/* @__PURE__ */ u("div", {
|
|
66
66
|
className: "flex items-center gap-2",
|
|
67
67
|
children: [/* @__PURE__ */ l("span", {
|
|
68
|
-
className: "font-medium text-
|
|
68
|
+
className: "font-medium text-text-primary truncate",
|
|
69
69
|
children: C.name
|
|
70
70
|
}), !C.isActive && /* @__PURE__ */ l("span", {
|
|
71
|
-
className: "text-xs px-1.5 py-0.5 rounded bg-
|
|
71
|
+
className: "text-xs px-1.5 py-0.5 rounded bg-status-error-bg-subtle text-status-error-text shrink-0",
|
|
72
72
|
children: "Inactive"
|
|
73
73
|
})]
|
|
74
74
|
}), /* @__PURE__ */ l("p", {
|
|
75
|
-
className: "text-sm text-
|
|
75
|
+
className: "text-sm text-text-secondary truncate",
|
|
76
76
|
children: C.email
|
|
77
77
|
})]
|
|
78
78
|
}),
|
|
79
79
|
/* @__PURE__ */ l("div", {
|
|
80
80
|
className: "shrink-0 text-right",
|
|
81
81
|
children: /* @__PURE__ */ u("div", {
|
|
82
|
-
className: "flex items-center gap-1 text-sm font-medium text-
|
|
83
|
-
children: [/* @__PURE__ */ l(s, { className: "size-3.5 text-
|
|
82
|
+
className: "flex items-center gap-1 text-sm font-medium text-text-primary",
|
|
83
|
+
children: [/* @__PURE__ */ l(s, { className: "size-3.5 text-text-secondary" }), e(C.creditAmount, "CREDITS")]
|
|
84
84
|
})
|
|
85
85
|
})
|
|
86
86
|
]
|
|
87
87
|
}) : /* @__PURE__ */ l("span", {
|
|
88
|
-
className: "text-
|
|
88
|
+
className: "text-text-secondary",
|
|
89
89
|
children: "Select billing account"
|
|
90
|
-
}), g ? /* @__PURE__ */ l(c, { className: "size-4 shrink-0 text-
|
|
90
|
+
}), g ? /* @__PURE__ */ l(c, { className: "size-4 shrink-0 text-text-secondary" }) : /* @__PURE__ */ l(o, { className: `size-4 shrink-0 text-text-secondary transition-transform ${b ? "rotate-180" : ""}` })]
|
|
91
91
|
}),
|
|
92
92
|
g && _ && /* @__PURE__ */ l("p", {
|
|
93
|
-
className: "text-xs text-
|
|
93
|
+
className: "text-xs text-text-secondary",
|
|
94
94
|
children: _
|
|
95
95
|
}),
|
|
96
96
|
b && !g && /* @__PURE__ */ l("div", {
|
|
97
|
-
className: "absolute left-0 right-0 z-50 mt-1 max-h-64 overflow-auto rounded-
|
|
97
|
+
className: "absolute left-0 right-0 z-50 mt-1 max-h-64 overflow-auto rounded-card border border-border-subtle bg-bg-elevated shadow-elevation-3",
|
|
98
98
|
children: f.map((t) => {
|
|
99
99
|
let n = t.id === p;
|
|
100
100
|
return /* @__PURE__ */ u("button", {
|
|
@@ -105,11 +105,11 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
105
105
|
className: `
|
|
106
106
|
w-full flex items-center gap-3 p-3 text-left
|
|
107
107
|
transition-colors
|
|
108
|
-
${n ? "bg-
|
|
108
|
+
${n ? "bg-[var(--color-accent-soft)]" : "hover:bg-bg-sunken"}
|
|
109
109
|
`,
|
|
110
110
|
children: [
|
|
111
111
|
/* @__PURE__ */ l("div", {
|
|
112
|
-
className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-
|
|
112
|
+
className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)] text-text-link",
|
|
113
113
|
children: /* @__PURE__ */ l(i, { className: "size-4" })
|
|
114
114
|
}),
|
|
115
115
|
/* @__PURE__ */ u("div", {
|
|
@@ -117,14 +117,14 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
117
117
|
children: [/* @__PURE__ */ u("div", {
|
|
118
118
|
className: "flex items-center gap-2",
|
|
119
119
|
children: [/* @__PURE__ */ l("span", {
|
|
120
|
-
className: "font-medium text-
|
|
120
|
+
className: "font-medium text-text-primary truncate",
|
|
121
121
|
children: t.name
|
|
122
122
|
}), !t.isActive && /* @__PURE__ */ l("span", {
|
|
123
|
-
className: "text-xs px-1.5 py-0.5 rounded bg-
|
|
123
|
+
className: "text-xs px-1.5 py-0.5 rounded bg-status-error-bg-subtle text-status-error-text shrink-0",
|
|
124
124
|
children: "Inactive"
|
|
125
125
|
})]
|
|
126
126
|
}), /* @__PURE__ */ l("p", {
|
|
127
|
-
className: "text-sm text-
|
|
127
|
+
className: "text-sm text-text-secondary truncate",
|
|
128
128
|
children: t.email
|
|
129
129
|
})]
|
|
130
130
|
}),
|
|
@@ -133,10 +133,10 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
|
|
|
133
133
|
children: [/* @__PURE__ */ l("div", {
|
|
134
134
|
className: "text-right",
|
|
135
135
|
children: /* @__PURE__ */ u("div", {
|
|
136
|
-
className: "flex items-center gap-1 text-sm font-medium text-
|
|
137
|
-
children: [/* @__PURE__ */ l(s, { className: "size-3.5 text-
|
|
136
|
+
className: "flex items-center gap-1 text-sm font-medium text-text-primary",
|
|
137
|
+
children: [/* @__PURE__ */ l(s, { className: "size-3.5 text-text-secondary" }), e(t.creditAmount, "CREDITS")]
|
|
138
138
|
})
|
|
139
|
-
}), n && /* @__PURE__ */ l(a, { className: "size-4 text-
|
|
139
|
+
}), n && /* @__PURE__ */ l(a, { className: "size-4 text-text-link" })]
|
|
140
140
|
})
|
|
141
141
|
]
|
|
142
142
|
}, t.id);
|