@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
|
@@ -27,10 +27,10 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
27
27
|
maximumFractionDigits: 2
|
|
28
28
|
}).format(e), w = (e) => e === "yearly" ? "year" : "month", T = t(() => _(e.features || []), [e.features]);
|
|
29
29
|
return /* @__PURE__ */ h("article", {
|
|
30
|
-
className: "flex flex-col border border-border rounded-
|
|
30
|
+
className: "flex flex-col border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden hover:border-border-strong hover:shadow-elevation-2 hover:-translate-y-0.5 transition-all duration-200",
|
|
31
31
|
children: [
|
|
32
32
|
/* @__PURE__ */ m("header", {
|
|
33
|
-
className: "p-4 border-b border-border",
|
|
33
|
+
className: "p-4 border-b border-border-subtle",
|
|
34
34
|
children: /* @__PURE__ */ m("div", {
|
|
35
35
|
className: "flex items-start justify-between gap-3",
|
|
36
36
|
children: /* @__PURE__ */ h("div", {
|
|
@@ -39,10 +39,10 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
39
39
|
className: "size-10 rounded-lg bg-status-success-bg-subtle flex items-center justify-center",
|
|
40
40
|
children: /* @__PURE__ */ m(c, { className: "size-5 text-status-success-text" })
|
|
41
41
|
}), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h4", {
|
|
42
|
-
className: "font-semibold text-
|
|
42
|
+
className: "font-semibold text-text-primary",
|
|
43
43
|
children: e.name
|
|
44
44
|
}), /* @__PURE__ */ h("p", {
|
|
45
|
-
className: "text-sm text-
|
|
45
|
+
className: "text-sm text-text-secondary",
|
|
46
46
|
children: [
|
|
47
47
|
C(e.price, e.currency),
|
|
48
48
|
"/",
|
|
@@ -61,15 +61,15 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
61
61
|
children: [/* @__PURE__ */ h("div", {
|
|
62
62
|
className: "flex items-center gap-2",
|
|
63
63
|
children: [/* @__PURE__ */ m("span", { className: "size-1.5 rounded-full bg-status-success-bg" }), /* @__PURE__ */ m("span", {
|
|
64
|
-
className: "text-
|
|
64
|
+
className: "text-text-secondary",
|
|
65
65
|
children: e.name
|
|
66
66
|
})]
|
|
67
67
|
}), /* @__PURE__ */ m("span", {
|
|
68
|
-
className: "font-medium text-
|
|
68
|
+
className: "font-medium text-text-primary",
|
|
69
69
|
children: e.totalValue.toLocaleString()
|
|
70
70
|
})]
|
|
71
71
|
}, e.quotaId)), T.length > 2 && /* @__PURE__ */ h("li", {
|
|
72
|
-
className: "text-xs text-
|
|
72
|
+
className: "text-xs text-text-secondary",
|
|
73
73
|
children: [
|
|
74
74
|
"+",
|
|
75
75
|
T.length - 2,
|
|
@@ -77,16 +77,16 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
77
77
|
]
|
|
78
78
|
})]
|
|
79
79
|
}) : /* @__PURE__ */ m("p", {
|
|
80
|
-
className: "text-sm text-
|
|
80
|
+
className: "text-sm text-text-secondary",
|
|
81
81
|
children: "Enhance your subscription with additional features"
|
|
82
82
|
})
|
|
83
83
|
}),
|
|
84
84
|
/* @__PURE__ */ h("footer", {
|
|
85
|
-
className: "p-4 border-t border-border bg-
|
|
85
|
+
className: "p-4 border-t border-border-subtle bg-bg-sunken flex items-center gap-2",
|
|
86
86
|
children: [/* @__PURE__ */ m("button", {
|
|
87
87
|
type: "button",
|
|
88
88
|
onClick: r,
|
|
89
|
-
className: "flex-1 px-3 py-2 text-sm font-medium text-
|
|
89
|
+
className: "flex-1 px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button transition-colors text-center",
|
|
90
90
|
children: "View Details"
|
|
91
91
|
}), d && v ? /* @__PURE__ */ h("div", {
|
|
92
92
|
className: "flex items-center gap-1",
|
|
@@ -94,24 +94,24 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
94
94
|
/* @__PURE__ */ m("button", {
|
|
95
95
|
type: "button",
|
|
96
96
|
onClick: y,
|
|
97
|
-
className: "p-2 text-
|
|
97
|
+
className: "p-2 text-status-error-text hover:bg-status-error-bg-subtle rounded-button transition-colors",
|
|
98
98
|
title: "Remove from cart",
|
|
99
99
|
children: /* @__PURE__ */ m(f, { className: "size-4" })
|
|
100
100
|
}),
|
|
101
101
|
/* @__PURE__ */ m("button", {
|
|
102
102
|
type: "button",
|
|
103
103
|
onClick: () => v(g - 1),
|
|
104
|
-
className: "p-2 text-
|
|
104
|
+
className: "p-2 text-text-primary hover:bg-bg-sunken rounded-button transition-colors",
|
|
105
105
|
children: /* @__PURE__ */ m(s, { className: "size-4" })
|
|
106
106
|
}),
|
|
107
107
|
/* @__PURE__ */ m("span", {
|
|
108
|
-
className: "w-8 text-center font-medium text-
|
|
108
|
+
className: "w-8 text-center font-medium text-text-primary",
|
|
109
109
|
children: g
|
|
110
110
|
}),
|
|
111
111
|
/* @__PURE__ */ m("button", {
|
|
112
112
|
type: "button",
|
|
113
113
|
onClick: () => v(g + 1),
|
|
114
|
-
className: "p-2 text-
|
|
114
|
+
className: "p-2 text-text-primary hover:bg-bg-sunken rounded-button transition-colors",
|
|
115
115
|
children: /* @__PURE__ */ m(l, { className: "size-4" })
|
|
116
116
|
})
|
|
117
117
|
]
|
|
@@ -119,7 +119,7 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
119
119
|
type: "button",
|
|
120
120
|
onClick: S,
|
|
121
121
|
disabled: b,
|
|
122
|
-
className: `flex-1 px-3 py-2 text-sm font-medium rounded-lg transition-colors text-center flex items-center justify-center gap-1.5 ${b ? "bg-status-success-bg text-primary-
|
|
122
|
+
className: `flex-1 px-3 py-2 text-sm font-medium rounded-lg transition-colors text-center flex items-center justify-center gap-1.5 ${b ? "bg-status-success-bg text-action-primary-text hover:bg-status-success-bg/90" : "text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bgHover"}`,
|
|
123
123
|
children: b ? /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(i, { className: "size-4" }), "Added"] }) : /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m(u, { className: "size-4" }), "Add to Cart"] })
|
|
124
124
|
})]
|
|
125
125
|
})
|
|
@@ -136,14 +136,14 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
136
136
|
className: `space-y-4 ${b}`,
|
|
137
137
|
"data-tour": x,
|
|
138
138
|
children: [/* @__PURE__ */ h("header", { children: [/* @__PURE__ */ m("h3", {
|
|
139
|
-
className: "text-lg font-semibold text-
|
|
139
|
+
className: "text-lg font-semibold text-text-primary",
|
|
140
140
|
children: C("billing.overview.recommendedAddons", "Recommended Add-ons")
|
|
141
141
|
}), /* @__PURE__ */ m("p", {
|
|
142
|
-
className: "text-sm text-
|
|
142
|
+
className: "text-sm text-text-secondary",
|
|
143
143
|
children: "Enhance your subscription with these popular add-ons"
|
|
144
144
|
})] }), /* @__PURE__ */ m("div", {
|
|
145
145
|
className: "flex items-center justify-center py-12",
|
|
146
|
-
children: /* @__PURE__ */ m(o, { className: "size-6 animate-spin text-
|
|
146
|
+
children: /* @__PURE__ */ m(o, { className: "size-6 animate-spin text-text-secondary" })
|
|
147
147
|
})]
|
|
148
148
|
}) : w.length === 0 ? null : /* @__PURE__ */ h("section", {
|
|
149
149
|
className: `space-y-4 ${b}`,
|
|
@@ -154,16 +154,16 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
154
154
|
children: [/* @__PURE__ */ h("div", {
|
|
155
155
|
className: "flex items-center gap-2",
|
|
156
156
|
children: [/* @__PURE__ */ m(d, { className: "size-5 text-status-warning-text" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h3", {
|
|
157
|
-
className: "text-lg font-semibold text-
|
|
157
|
+
className: "text-lg font-semibold text-text-primary",
|
|
158
158
|
children: "Recommended Add-ons"
|
|
159
159
|
}), /* @__PURE__ */ m("p", {
|
|
160
|
-
className: "text-sm text-
|
|
160
|
+
className: "text-sm text-text-secondary",
|
|
161
161
|
children: "Enhance your subscription with these popular add-ons"
|
|
162
162
|
})] })]
|
|
163
163
|
}), /* @__PURE__ */ h("button", {
|
|
164
164
|
type: "button",
|
|
165
165
|
onClick: s,
|
|
166
|
-
className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-
|
|
166
|
+
className: "inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-text-link hover:text-text-link transition-colors",
|
|
167
167
|
children: ["View All", /* @__PURE__ */ m(a, { className: "size-4" })]
|
|
168
168
|
})]
|
|
169
169
|
}),
|
|
@@ -185,7 +185,7 @@ var v = ({ addon: e, onView: r, onPurchase: a, onAddToCart: o, isInCart: d = !1,
|
|
|
185
185
|
children: /* @__PURE__ */ h("button", {
|
|
186
186
|
type: "button",
|
|
187
187
|
onClick: s,
|
|
188
|
-
className: "inline-flex items-center gap-2 text-sm font-medium text-
|
|
188
|
+
className: "inline-flex items-center gap-2 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors",
|
|
189
189
|
children: [
|
|
190
190
|
"View all ",
|
|
191
191
|
e.length,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RecommendedAddonsSection.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/RecommendedAddonsSection.tsx"],"sourcesContent":["/**\n * Recommended Addons Section Component\n * Displays recommended addons that users might want to purchase\n * Supports add to cart functionality\n */\n\nimport { type FC, useState, useMemo } from 'react';\nimport {\n Package,\n ArrowRight,\n Sparkles,\n ChevronRight,\n Loader2,\n ShoppingCart,\n Check,\n Plus,\n Minus,\n Trash2,\n} from 'lucide-react';\nimport type { Addon, PlanDuration, SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { getPlanFeatureQuantity } from '../../../shared/utils/planFeatureQuantity';\n\n/**\n * Combined quota info for display\n */\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n}\n\n/**\n * Combines duplicate quotas by quota ID and aggregates their values\n * e.g., 10 bots + 10 bots = 20 bots (shown as one feature)\n */\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n\n for (const feature of features) {\n if (!feature.quota) continue;\n\n const quotaId = feature.quota.id;\n const limitValue = getPlanFeatureQuantity(feature);\n\n const existing = quotaMap.get(quotaId);\n if (existing) {\n existing.totalValue += limitValue;\n } else {\n quotaMap.set(quotaId, {\n quotaId,\n name: feature.quota.name ?? 'Unknown Quota',\n totalValue: limitValue,\n });\n }\n }\n\n return Array.from(quotaMap.values());\n}\n\ninterface RecommendedAddonsSectionProps {\n addons: Addon[];\n hasSubscription: boolean;\n onViewAddon: (addonId: string) => void;\n onPurchaseAddon: (addonId: string) => void;\n onViewAllAddons: () => void;\n /** Handler for adding addon to cart */\n onAddToCart?: (addon: Addon) => void;\n /** Check if addon is in cart */\n isInCart?: (addonId: string) => boolean;\n /** Get cart quantity for addon */\n getCartQuantity?: (addonId: string) => number;\n /** Update quantity in cart */\n onUpdateQuantity?: (addonId: string, quantity: number) => void;\n /** Remove from cart */\n onRemoveFromCart?: (addonId: string) => void;\n /** Maximum number of addons to show (default: 3) */\n maxAddons?: number;\n isLoading?: boolean;\n className?: string;\n /** Optional tour anchor applied to the section root (for onboarding tours). */\n dataTour?: string;\n}\n\nconst AddonCard: FC<{\n addon: Addon;\n onView: () => void;\n onPurchase: () => void;\n onAddToCart?: () => void;\n isInCart?: boolean;\n cartQuantity?: number;\n onUpdateQuantity?: (quantity: number) => void;\n onRemoveFromCart?: () => void;\n}> = ({\n addon,\n onView,\n onPurchase,\n onAddToCart,\n isInCart = false,\n cartQuantity = 0,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const [justAdded, setJustAdded] = useState(false);\n\n const handleAddToCart = () => {\n if (onAddToCart) {\n onAddToCart();\n setJustAdded(true);\n setTimeout(() => setJustAdded(false), 2000);\n } else {\n onPurchase();\n }\n };\n\n const formatCurrency = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n }).format(amount);\n };\n\n const getDurationLabel = (duration: PlanDuration) => {\n return duration === 'yearly' ? 'year' : 'month';\n };\n\n // Combine duplicate quotas (e.g., 10 bots + 10 bots = 20 bots)\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features as SubscriptionFeatures[]);\n }, [addon.features]);\n\n return (\n <article className=\"flex flex-col border border-border rounded-lg bg-card overflow-hidden hover:shadow-md transition-shadow\">\n {/* Header */}\n <header className=\"p-4 border-b border-border\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-status-success-bg-subtle flex items-center justify-center\">\n <Package className=\"size-5 text-status-success-text\" />\n </div>\n <div>\n <h4 className=\"font-semibold text-foreground\">{addon.name}</h4>\n <p className=\"text-sm text-muted-foreground\">\n {formatCurrency(addon.price, addon.currency)}/{getDurationLabel(addon.duration)}\n </p>\n </div>\n </div>\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 flex-1\">\n {combinedQuotas.length > 0 ? (\n <ul className=\"space-y-2\">\n {combinedQuotas.slice(0, 2).map((quota) => (\n <li key={quota.quotaId} className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n <span className=\"size-1.5 rounded-full bg-status-success-bg\" />\n <span className=\"text-muted-foreground\">{quota.name}</span>\n </div>\n <span className=\"font-medium text-foreground\">\n {quota.totalValue.toLocaleString()}\n </span>\n </li>\n ))}\n {combinedQuotas.length > 2 && (\n <li className=\"text-xs text-muted-foreground\">\n +{combinedQuotas.length - 2} more quotas\n </li>\n )}\n </ul>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n Enhance your subscription with additional features\n </p>\n )}\n </div>\n\n {/* Footer */}\n <footer className=\"p-4 border-t border-border bg-muted/30 flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={onView}\n className=\"flex-1 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-lg transition-colors text-center\"\n >\n View Details\n </button>\n {isInCart && onUpdateQuantity ? (\n // Quantity controls when in cart\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={onRemoveFromCart}\n className=\"p-2 text-destructive hover:bg-destructive/10 rounded-lg transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(cartQuantity - 1)}\n className=\"p-2 text-foreground hover:bg-muted rounded-lg transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-8 text-center font-medium text-foreground\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(cartQuantity + 1)}\n className=\"p-2 text-foreground hover:bg-muted rounded-lg transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n </div>\n ) : (\n // Add to cart button\n <button\n type=\"button\"\n onClick={handleAddToCart}\n disabled={justAdded}\n className={`flex-1 px-3 py-2 text-sm font-medium rounded-lg transition-colors text-center flex items-center justify-center gap-1.5 ${\n justAdded\n ? 'bg-status-success-bg text-primary-foreground hover:bg-status-success-bg/90'\n : 'text-primary-foreground bg-primary hover:bg-primary/90'\n }`}\n >\n {justAdded ? (\n <>\n <Check className=\"size-4\" />\n Added\n </>\n ) : (\n <>\n <ShoppingCart className=\"size-4\" />\n Add to Cart\n </>\n )}\n </button>\n )}\n </footer>\n </article>\n );\n};\n\nexport const RecommendedAddonsSection: FC<RecommendedAddonsSectionProps> = ({\n addons,\n hasSubscription,\n onViewAddon,\n onPurchaseAddon,\n onViewAllAddons,\n onAddToCart,\n isInCart,\n getCartQuantity,\n onUpdateQuantity,\n onRemoveFromCart,\n maxAddons = 3,\n isLoading = false,\n className = '',\n dataTour,\n}) => {\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 // Only show if user has a subscription\n if (!hasSubscription) {\n return null;\n }\n\n // Limit addons to maxAddons\n const displayAddons = addons.slice(0, maxAddons);\n\n if (isLoading) {\n return (\n <section className={`space-y-4 ${className}`} data-tour={dataTour}>\n <header>\n <h3 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.overview.recommendedAddons', 'Recommended Add-ons')}\n </h3>\n <p className=\"text-sm text-muted-foreground\">\n Enhance your subscription with these popular add-ons\n </p>\n </header>\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"size-6 animate-spin text-muted-foreground\" />\n </div>\n </section>\n );\n }\n\n if (displayAddons.length === 0) {\n return null;\n }\n\n return (\n <section className={`space-y-4 ${className}`} data-tour={dataTour}>\n {/* Header */}\n <header className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Sparkles className=\"size-5 text-status-warning-text\" />\n <div>\n <h3 className=\"text-lg font-semibold text-foreground\">Recommended Add-ons</h3>\n <p className=\"text-sm text-muted-foreground\">\n Enhance your subscription with these popular add-ons\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onViewAllAddons}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-primary hover:text-primary/80 transition-colors\"\n >\n View All\n <ChevronRight className=\"size-4\" />\n </button>\n </header>\n\n {/* Addons Grid - Limited to maxAddons */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {displayAddons.map((addon) => (\n <AddonCard\n key={addon.id}\n addon={addon}\n onView={() => onViewAddon(addon.id)}\n onPurchase={() => onPurchaseAddon(addon.id)}\n onAddToCart={onAddToCart ? () => onAddToCart(addon) : undefined}\n isInCart={isInCart ? isInCart(addon.id) : false}\n cartQuantity={getCartQuantity ? getCartQuantity(addon.id) : 0}\n onUpdateQuantity={\n onUpdateQuantity ? (qty) => onUpdateQuantity(addon.id, qty) : undefined\n }\n onRemoveFromCart={onRemoveFromCart ? () => onRemoveFromCart(addon.id) : undefined}\n />\n ))}\n </div>\n\n {/* See More Link - show if there are more addons */}\n {addons.length > maxAddons && (\n <div className=\"flex justify-center pt-2\">\n <button\n type=\"button\"\n onClick={onViewAllAddons}\n className=\"inline-flex items-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\n >\n View all {addons.length} add-ons\n <ArrowRight className=\"size-4\" />\n </button>\n </div>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RecommendedAddonsSection.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/RecommendedAddonsSection.tsx"],"sourcesContent":["/**\n * Recommended Addons Section Component\n * Displays recommended addons that users might want to purchase\n * Supports add to cart functionality\n */\n\nimport { type FC, useState, useMemo } from 'react';\nimport {\n Package,\n ArrowRight,\n Sparkles,\n ChevronRight,\n Loader2,\n ShoppingCart,\n Check,\n Plus,\n Minus,\n Trash2,\n} from 'lucide-react';\nimport type { Addon, PlanDuration, SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { getPlanFeatureQuantity } from '../../../shared/utils/planFeatureQuantity';\n\n/**\n * Combined quota info for display\n */\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n}\n\n/**\n * Combines duplicate quotas by quota ID and aggregates their values\n * e.g., 10 bots + 10 bots = 20 bots (shown as one feature)\n */\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n\n for (const feature of features) {\n if (!feature.quota) continue;\n\n const quotaId = feature.quota.id;\n const limitValue = getPlanFeatureQuantity(feature);\n\n const existing = quotaMap.get(quotaId);\n if (existing) {\n existing.totalValue += limitValue;\n } else {\n quotaMap.set(quotaId, {\n quotaId,\n name: feature.quota.name ?? 'Unknown Quota',\n totalValue: limitValue,\n });\n }\n }\n\n return Array.from(quotaMap.values());\n}\n\ninterface RecommendedAddonsSectionProps {\n addons: Addon[];\n hasSubscription: boolean;\n onViewAddon: (addonId: string) => void;\n onPurchaseAddon: (addonId: string) => void;\n onViewAllAddons: () => void;\n /** Handler for adding addon to cart */\n onAddToCart?: (addon: Addon) => void;\n /** Check if addon is in cart */\n isInCart?: (addonId: string) => boolean;\n /** Get cart quantity for addon */\n getCartQuantity?: (addonId: string) => number;\n /** Update quantity in cart */\n onUpdateQuantity?: (addonId: string, quantity: number) => void;\n /** Remove from cart */\n onRemoveFromCart?: (addonId: string) => void;\n /** Maximum number of addons to show (default: 3) */\n maxAddons?: number;\n isLoading?: boolean;\n className?: string;\n /** Optional tour anchor applied to the section root (for onboarding tours). */\n dataTour?: string;\n}\n\nconst AddonCard: FC<{\n addon: Addon;\n onView: () => void;\n onPurchase: () => void;\n onAddToCart?: () => void;\n isInCart?: boolean;\n cartQuantity?: number;\n onUpdateQuantity?: (quantity: number) => void;\n onRemoveFromCart?: () => void;\n}> = ({\n addon,\n onView,\n onPurchase,\n onAddToCart,\n isInCart = false,\n cartQuantity = 0,\n onUpdateQuantity,\n onRemoveFromCart,\n}) => {\n const [justAdded, setJustAdded] = useState(false);\n\n const handleAddToCart = () => {\n if (onAddToCart) {\n onAddToCart();\n setJustAdded(true);\n setTimeout(() => setJustAdded(false), 2000);\n } else {\n onPurchase();\n }\n };\n\n const formatCurrency = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n minimumFractionDigits: 0,\n maximumFractionDigits: 2,\n }).format(amount);\n };\n\n const getDurationLabel = (duration: PlanDuration) => {\n return duration === 'yearly' ? 'year' : 'month';\n };\n\n // Combine duplicate quotas (e.g., 10 bots + 10 bots = 20 bots)\n const combinedQuotas = useMemo(() => {\n const features = addon.features || [];\n return combineQuotas(features as SubscriptionFeatures[]);\n }, [addon.features]);\n\n return (\n <article className=\"flex flex-col border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden hover:border-border-strong hover:shadow-elevation-2 hover:-translate-y-0.5 transition-all duration-200\">\n {/* Header */}\n <header className=\"p-4 border-b border-border-subtle\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-status-success-bg-subtle flex items-center justify-center\">\n <Package className=\"size-5 text-status-success-text\" />\n </div>\n <div>\n <h4 className=\"font-semibold text-text-primary\">{addon.name}</h4>\n <p className=\"text-sm text-text-secondary\">\n {formatCurrency(addon.price, addon.currency)}/{getDurationLabel(addon.duration)}\n </p>\n </div>\n </div>\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 flex-1\">\n {combinedQuotas.length > 0 ? (\n <ul className=\"space-y-2\">\n {combinedQuotas.slice(0, 2).map((quota) => (\n <li key={quota.quotaId} className=\"flex items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n <span className=\"size-1.5 rounded-full bg-status-success-bg\" />\n <span className=\"text-text-secondary\">{quota.name}</span>\n </div>\n <span className=\"font-medium text-text-primary\">\n {quota.totalValue.toLocaleString()}\n </span>\n </li>\n ))}\n {combinedQuotas.length > 2 && (\n <li className=\"text-xs text-text-secondary\">\n +{combinedQuotas.length - 2} more quotas\n </li>\n )}\n </ul>\n ) : (\n <p className=\"text-sm text-text-secondary\">\n Enhance your subscription with additional features\n </p>\n )}\n </div>\n\n {/* Footer */}\n <footer className=\"p-4 border-t border-border-subtle bg-bg-sunken flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={onView}\n className=\"flex-1 px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button transition-colors text-center\"\n >\n View Details\n </button>\n {isInCart && onUpdateQuantity ? (\n // Quantity controls when in cart\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={onRemoveFromCart}\n className=\"p-2 text-status-error-text hover:bg-status-error-bg-subtle rounded-button transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(cartQuantity - 1)}\n className=\"p-2 text-text-primary hover:bg-bg-sunken rounded-button transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-8 text-center font-medium text-text-primary\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => onUpdateQuantity(cartQuantity + 1)}\n className=\"p-2 text-text-primary hover:bg-bg-sunken rounded-button transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n </div>\n ) : (\n // Add to cart button\n <button\n type=\"button\"\n onClick={handleAddToCart}\n disabled={justAdded}\n className={`flex-1 px-3 py-2 text-sm font-medium rounded-lg transition-colors text-center flex items-center justify-center gap-1.5 ${\n justAdded\n ? 'bg-status-success-bg text-action-primary-text hover:bg-status-success-bg/90'\n : 'text-action-primary-text bg-action-primary-bg hover:bg-action-primary-bgHover'\n }`}\n >\n {justAdded ? (\n <>\n <Check className=\"size-4\" />\n Added\n </>\n ) : (\n <>\n <ShoppingCart className=\"size-4\" />\n Add to Cart\n </>\n )}\n </button>\n )}\n </footer>\n </article>\n );\n};\n\nexport const RecommendedAddonsSection: FC<RecommendedAddonsSectionProps> = ({\n addons,\n hasSubscription,\n onViewAddon,\n onPurchaseAddon,\n onViewAllAddons,\n onAddToCart,\n isInCart,\n getCartQuantity,\n onUpdateQuantity,\n onRemoveFromCart,\n maxAddons = 3,\n isLoading = false,\n className = '',\n dataTour,\n}) => {\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 // Only show if user has a subscription\n if (!hasSubscription) {\n return null;\n }\n\n // Limit addons to maxAddons\n const displayAddons = addons.slice(0, maxAddons);\n\n if (isLoading) {\n return (\n <section className={`space-y-4 ${className}`} data-tour={dataTour}>\n <header>\n <h3 className=\"text-lg font-semibold text-text-primary\">\n {tr('billing.overview.recommendedAddons', 'Recommended Add-ons')}\n </h3>\n <p className=\"text-sm text-text-secondary\">\n Enhance your subscription with these popular add-ons\n </p>\n </header>\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"size-6 animate-spin text-text-secondary\" />\n </div>\n </section>\n );\n }\n\n if (displayAddons.length === 0) {\n return null;\n }\n\n return (\n <section className={`space-y-4 ${className}`} data-tour={dataTour}>\n {/* Header */}\n <header className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <Sparkles className=\"size-5 text-status-warning-text\" />\n <div>\n <h3 className=\"text-lg font-semibold text-text-primary\">Recommended Add-ons</h3>\n <p className=\"text-sm text-text-secondary\">\n Enhance your subscription with these popular add-ons\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onViewAllAddons}\n className=\"inline-flex items-center gap-1.5 px-3 py-1.5 text-sm font-medium text-text-link hover:text-text-link transition-colors\"\n >\n View All\n <ChevronRight className=\"size-4\" />\n </button>\n </header>\n\n {/* Addons Grid - Limited to maxAddons */}\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n {displayAddons.map((addon) => (\n <AddonCard\n key={addon.id}\n addon={addon}\n onView={() => onViewAddon(addon.id)}\n onPurchase={() => onPurchaseAddon(addon.id)}\n onAddToCart={onAddToCart ? () => onAddToCart(addon) : undefined}\n isInCart={isInCart ? isInCart(addon.id) : false}\n cartQuantity={getCartQuantity ? getCartQuantity(addon.id) : 0}\n onUpdateQuantity={\n onUpdateQuantity ? (qty) => onUpdateQuantity(addon.id, qty) : undefined\n }\n onRemoveFromCart={onRemoveFromCart ? () => onRemoveFromCart(addon.id) : undefined}\n />\n ))}\n </div>\n\n {/* See More Link - show if there are more addons */}\n {addons.length > maxAddons && (\n <div className=\"flex justify-center pt-2\">\n <button\n type=\"button\"\n onClick={onViewAllAddons}\n className=\"inline-flex items-center gap-2 text-sm font-medium text-text-secondary hover:text-text-primary transition-colors\"\n >\n View all {addons.length} add-ons\n <ArrowRight className=\"size-4\" />\n </button>\n </div>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
|
|
@@ -131,32 +131,32 @@ var g = () => {
|
|
|
131
131
|
className: "flex items-center justify-center min-h-[400px]",
|
|
132
132
|
children: /* @__PURE__ */ h("div", {
|
|
133
133
|
className: "flex flex-col items-center gap-3",
|
|
134
|
-
children: [/* @__PURE__ */ m(xe, { className: "size-8 animate-spin text-
|
|
135
|
-
className: "text-sm text-
|
|
134
|
+
children: [/* @__PURE__ */ m(xe, { className: "size-8 animate-spin text-text-link" }), /* @__PURE__ */ m("p", {
|
|
135
|
+
className: "text-sm text-text-secondary",
|
|
136
136
|
children: _("billing.overview.loadingInfo", "Loading billing information...")
|
|
137
137
|
})]
|
|
138
138
|
})
|
|
139
139
|
}) : !R && N.length === 0 ? /* @__PURE__ */ h("div", {
|
|
140
|
-
className: "
|
|
140
|
+
className: "px-6 lg:px-8 py-6",
|
|
141
141
|
children: [
|
|
142
142
|
/* @__PURE__ */ h("header", {
|
|
143
143
|
className: "mb-8",
|
|
144
144
|
children: [/* @__PURE__ */ m("h1", {
|
|
145
|
-
className: "text-2xl font-
|
|
145
|
+
className: "text-2xl md:text-3xl font-semibold tracking-tight text-text-primary",
|
|
146
146
|
children: _("billing.overview.title", "Billing Overview")
|
|
147
147
|
}), /* @__PURE__ */ m("p", {
|
|
148
|
-
className: "text-sm text-
|
|
148
|
+
className: "text-sm text-text-secondary mt-1",
|
|
149
149
|
children: _("billing.overview.emptySetupDescription", "Set up billing to manage subscriptions, payments, and invoices")
|
|
150
150
|
})]
|
|
151
151
|
}),
|
|
152
152
|
/* @__PURE__ */ m(ee, {
|
|
153
|
-
icon: /* @__PURE__ */ m(c, { className: "size-6 text-
|
|
153
|
+
icon: /* @__PURE__ */ m(c, { className: "size-6 text-text-secondary" }),
|
|
154
154
|
title: _("billing.overview.emptyTitle", "No billing account"),
|
|
155
155
|
description: _("billing.overview.emptyDescription", "Create a billing account to start managing your subscriptions and payments"),
|
|
156
156
|
action: x.canManageBillingAccount ? /* @__PURE__ */ h("button", {
|
|
157
157
|
type: "button",
|
|
158
158
|
onClick: () => T(!0),
|
|
159
|
-
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-primary-
|
|
159
|
+
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-colors duration-200",
|
|
160
160
|
children: [/* @__PURE__ */ m(u, { className: "size-4" }), _("billing.overview.createBillingAccount", "Create Billing Account")]
|
|
161
161
|
}) : void 0
|
|
162
162
|
}),
|
|
@@ -171,28 +171,28 @@ var g = () => {
|
|
|
171
171
|
})
|
|
172
172
|
]
|
|
173
173
|
}) : /* @__PURE__ */ h("div", {
|
|
174
|
-
className: "
|
|
174
|
+
className: "px-6 lg:px-8 py-6 space-y-6 sm:space-y-8",
|
|
175
175
|
children: [
|
|
176
176
|
/* @__PURE__ */ h("header", {
|
|
177
177
|
className: "flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4",
|
|
178
178
|
children: [/* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h1", {
|
|
179
|
-
className: "text-2xl font-
|
|
179
|
+
className: "text-2xl md:text-3xl font-semibold tracking-tight text-text-primary",
|
|
180
180
|
children: _("billing.overview.title", "Billing Overview")
|
|
181
181
|
}), /* @__PURE__ */ m("p", {
|
|
182
|
-
className: "text-sm text-
|
|
182
|
+
className: "text-sm text-text-secondary mt-1",
|
|
183
183
|
children: _("billing.overview.description", "Manage your billing accounts, subscriptions, and payment methods")
|
|
184
184
|
})] }), /* @__PURE__ */ h("div", {
|
|
185
185
|
className: "flex items-center gap-2",
|
|
186
186
|
children: [/* @__PURE__ */ m("button", {
|
|
187
187
|
type: "button",
|
|
188
188
|
onClick: Be,
|
|
189
|
-
className: "p-2 rounded-
|
|
189
|
+
className: "p-2 rounded-button border border-border-subtle hover:bg-bg-sunken hover:border-border-strong text-text-secondary hover:text-text-primary transition-all duration-200",
|
|
190
190
|
"aria-label": _("billing.overview.refresh", "Refresh"),
|
|
191
191
|
children: /* @__PURE__ */ m(d, { className: `size-4 ${R ? "animate-spin" : ""}` })
|
|
192
192
|
}), x.canManageBillingAccount && N.length > 0 && /* @__PURE__ */ h("button", {
|
|
193
193
|
type: "button",
|
|
194
194
|
onClick: () => T(!0),
|
|
195
|
-
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-primary-
|
|
195
|
+
className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-colors duration-200",
|
|
196
196
|
children: [/* @__PURE__ */ m(u, { className: "size-4" }), /* @__PURE__ */ m("span", {
|
|
197
197
|
className: "hidden sm:inline",
|
|
198
198
|
children: _("billing.overview.newAccount", "New Account")
|
|
@@ -206,48 +206,48 @@ var g = () => {
|
|
|
206
206
|
children: [/* @__PURE__ */ h("button", {
|
|
207
207
|
type: "button",
|
|
208
208
|
onClick: () => k(!O),
|
|
209
|
-
className: "w-full sm:w-auto flex items-center justify-between gap-3 px-4 py-3 border border-border rounded-
|
|
209
|
+
className: "w-full sm:w-auto flex items-center justify-between gap-3 px-4 py-3 border border-border-subtle rounded-card bg-bg-surface hover:bg-bg-sunken hover:border-border-strong transition-all duration-200",
|
|
210
210
|
children: [/* @__PURE__ */ h("div", {
|
|
211
211
|
className: "flex items-center gap-3",
|
|
212
212
|
children: [/* @__PURE__ */ m("div", {
|
|
213
|
-
className: "size-
|
|
214
|
-
children: /* @__PURE__ */ m(c, { className: "size-4 text-
|
|
213
|
+
className: "size-9 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
|
|
214
|
+
children: /* @__PURE__ */ m(c, { className: "size-4 text-text-link" })
|
|
215
215
|
}), /* @__PURE__ */ h("div", {
|
|
216
216
|
className: "text-left",
|
|
217
217
|
children: [/* @__PURE__ */ m("p", {
|
|
218
|
-
className: "text-sm font-medium text-
|
|
218
|
+
className: "text-sm font-medium text-text-primary",
|
|
219
219
|
children: P?.name || _("billing.overview.selectAccount", "Select Account")
|
|
220
220
|
}), /* @__PURE__ */ m("p", {
|
|
221
|
-
className: "text-xs text-
|
|
221
|
+
className: "text-xs text-text-secondary",
|
|
222
222
|
children: P?.email
|
|
223
223
|
})]
|
|
224
224
|
})]
|
|
225
|
-
}), /* @__PURE__ */ m(ye, { className: `size-4 text-muted
|
|
225
|
+
}), /* @__PURE__ */ m(ye, { className: `size-4 text-text-muted transition-transform ${O ? "rotate-180" : ""}` })]
|
|
226
226
|
}), O && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("div", {
|
|
227
227
|
className: "fixed inset-0 z-10",
|
|
228
228
|
onClick: () => k(!1)
|
|
229
229
|
}), /* @__PURE__ */ m("div", {
|
|
230
|
-
className: "absolute top-full left-0 right-0 sm:right-auto mt-1 w-full sm:w-80 bg-
|
|
230
|
+
className: "absolute top-full left-0 right-0 sm:right-auto mt-1 w-full sm:w-80 bg-bg-elevated border border-border-subtle rounded-card shadow-elevation-3 z-20 py-1 max-h-60 overflow-y-auto",
|
|
231
231
|
children: N.map((e) => /* @__PURE__ */ h("button", {
|
|
232
232
|
type: "button",
|
|
233
233
|
onClick: () => ze(e),
|
|
234
|
-
className: "w-full flex items-center justify-between gap-3 px-4 py-3 hover:bg-
|
|
234
|
+
className: "w-full flex items-center justify-between gap-3 px-4 py-3 hover:bg-bg-sunken transition-colors",
|
|
235
235
|
children: [/* @__PURE__ */ h("div", {
|
|
236
236
|
className: "flex items-center gap-3 min-w-0",
|
|
237
237
|
children: [/* @__PURE__ */ m("div", {
|
|
238
|
-
className: "size-
|
|
239
|
-
children: /* @__PURE__ */ m(c, { className: "size-4 text-
|
|
238
|
+
className: "size-9 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0",
|
|
239
|
+
children: /* @__PURE__ */ m(c, { className: "size-4 text-text-secondary" })
|
|
240
240
|
}), /* @__PURE__ */ h("div", {
|
|
241
241
|
className: "text-left min-w-0",
|
|
242
242
|
children: [/* @__PURE__ */ m("p", {
|
|
243
|
-
className: "text-sm font-medium text-
|
|
243
|
+
className: "text-sm font-medium text-text-primary truncate",
|
|
244
244
|
children: e.name
|
|
245
245
|
}), /* @__PURE__ */ m("p", {
|
|
246
|
-
className: "text-xs text-
|
|
246
|
+
className: "text-xs text-text-secondary truncate",
|
|
247
247
|
children: e.email
|
|
248
248
|
})]
|
|
249
249
|
})]
|
|
250
|
-
}), P?.id === e.id && /* @__PURE__ */ m(ve, { className: "size-4 text-
|
|
250
|
+
}), P?.id === e.id && /* @__PURE__ */ m(ve, { className: "size-4 text-text-link flex-shrink-0" })]
|
|
251
251
|
}, e.id))
|
|
252
252
|
})] })]
|
|
253
253
|
}),
|
|
@@ -297,18 +297,18 @@ var g = () => {
|
|
|
297
297
|
children: [/* @__PURE__ */ h("button", {
|
|
298
298
|
type: "button",
|
|
299
299
|
onClick: () => M(!j),
|
|
300
|
-
className: "w-full sm:w-auto flex items-center justify-between gap-3 px-4 py-3 border border-border rounded-
|
|
300
|
+
className: "w-full sm:w-auto flex items-center justify-between gap-3 px-4 py-3 border border-border-subtle rounded-card bg-bg-surface hover:bg-bg-sunken hover:border-border-strong transition-all duration-200",
|
|
301
301
|
children: [/* @__PURE__ */ h("div", {
|
|
302
302
|
className: "flex items-center gap-3",
|
|
303
303
|
children: [/* @__PURE__ */ m("div", {
|
|
304
|
-
className: "size-
|
|
305
|
-
children: /* @__PURE__ */ m(l, { className: "size-4 text-
|
|
304
|
+
className: "size-9 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
|
|
305
|
+
children: /* @__PURE__ */ m(l, { className: "size-4 text-text-link" })
|
|
306
306
|
}), /* @__PURE__ */ h("div", {
|
|
307
307
|
className: "text-left",
|
|
308
308
|
children: [/* @__PURE__ */ h("p", {
|
|
309
|
-
className: "text-sm font-medium text-
|
|
309
|
+
className: "text-sm font-medium text-text-primary",
|
|
310
310
|
children: [Z?.plan?.name || _("billing.overview.selectSubscription", "Select Subscription"), Z?.plan?.product?.name && /* @__PURE__ */ h("span", {
|
|
311
|
-
className: "text-
|
|
311
|
+
className: "text-text-secondary font-normal",
|
|
312
312
|
children: [
|
|
313
313
|
" ",
|
|
314
314
|
"· ",
|
|
@@ -316,7 +316,7 @@ var g = () => {
|
|
|
316
316
|
]
|
|
317
317
|
})]
|
|
318
318
|
}), /* @__PURE__ */ h("p", {
|
|
319
|
-
className: "text-xs text-
|
|
319
|
+
className: "text-xs text-text-secondary",
|
|
320
320
|
children: [
|
|
321
321
|
I.length,
|
|
322
322
|
" ",
|
|
@@ -324,30 +324,30 @@ var g = () => {
|
|
|
324
324
|
]
|
|
325
325
|
})]
|
|
326
326
|
})]
|
|
327
|
-
}), /* @__PURE__ */ m(ye, { className: `size-4 text-muted
|
|
327
|
+
}), /* @__PURE__ */ m(ye, { className: `size-4 text-text-muted transition-transform ${j ? "rotate-180" : ""}` })]
|
|
328
328
|
}), j && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ m("div", {
|
|
329
329
|
className: "fixed inset-0 z-10",
|
|
330
330
|
onClick: () => M(!1)
|
|
331
331
|
}), /* @__PURE__ */ m("div", {
|
|
332
|
-
className: "absolute top-full left-0 right-0 sm:right-auto mt-1 w-full sm:w-80 bg-
|
|
332
|
+
className: "absolute top-full left-0 right-0 sm:right-auto mt-1 w-full sm:w-80 bg-bg-elevated border border-border-subtle rounded-card shadow-elevation-3 z-20 py-1 max-h-60 overflow-y-auto",
|
|
333
333
|
children: I.map((e, t) => /* @__PURE__ */ h("button", {
|
|
334
334
|
type: "button",
|
|
335
335
|
onClick: () => {
|
|
336
336
|
ke(t), M(!1);
|
|
337
337
|
},
|
|
338
|
-
className: "w-full flex items-center justify-between gap-3 px-4 py-3 hover:bg-
|
|
338
|
+
className: "w-full flex items-center justify-between gap-3 px-4 py-3 hover:bg-bg-sunken transition-colors",
|
|
339
339
|
children: [/* @__PURE__ */ h("div", {
|
|
340
340
|
className: "flex items-center gap-3 min-w-0",
|
|
341
341
|
children: [/* @__PURE__ */ m("div", {
|
|
342
|
-
className: "size-
|
|
343
|
-
children: /* @__PURE__ */ m(l, { className: "size-4 text-
|
|
342
|
+
className: "size-9 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0",
|
|
343
|
+
children: /* @__PURE__ */ m(l, { className: "size-4 text-text-secondary" })
|
|
344
344
|
}), /* @__PURE__ */ h("div", {
|
|
345
345
|
className: "text-left min-w-0",
|
|
346
346
|
children: [/* @__PURE__ */ m("p", {
|
|
347
|
-
className: "text-sm font-medium text-
|
|
347
|
+
className: "text-sm font-medium text-text-primary truncate",
|
|
348
348
|
children: e.plan?.name || _("billing.overview.subscription", "Subscription")
|
|
349
349
|
}), /* @__PURE__ */ h("p", {
|
|
350
|
-
className: "text-xs text-
|
|
350
|
+
className: "text-xs text-text-secondary truncate",
|
|
351
351
|
children: [
|
|
352
352
|
e.plan?.product?.name || _("billing.overview.unknownProduct", "Unknown Product"),
|
|
353
353
|
" ",
|
|
@@ -358,7 +358,7 @@ var g = () => {
|
|
|
358
358
|
]
|
|
359
359
|
})]
|
|
360
360
|
})]
|
|
361
|
-
}), Oe === t && /* @__PURE__ */ m(ve, { className: "size-4 text-
|
|
361
|
+
}), Oe === t && /* @__PURE__ */ m(ve, { className: "size-4 text-text-link flex-shrink-0" })]
|
|
362
362
|
}, e.id))
|
|
363
363
|
})] })]
|
|
364
364
|
}), /* @__PURE__ */ m(de, {
|
|
@@ -383,40 +383,40 @@ var g = () => {
|
|
|
383
383
|
}), /* @__PURE__ */ h("div", {
|
|
384
384
|
className: "space-y-6",
|
|
385
385
|
children: [/* @__PURE__ */ h("section", {
|
|
386
|
-
className: "border border-border rounded-
|
|
386
|
+
className: "border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 p-5",
|
|
387
387
|
"data-tour": "billing-overview-quick-actions",
|
|
388
388
|
children: [/* @__PURE__ */ m("h3", {
|
|
389
|
-
className: "font-semibold text-
|
|
389
|
+
className: "font-semibold text-text-primary mb-4",
|
|
390
390
|
children: "Quick Actions"
|
|
391
391
|
}), /* @__PURE__ */ h("div", {
|
|
392
|
-
className: "space-y-
|
|
392
|
+
className: "space-y-1.5",
|
|
393
393
|
children: [
|
|
394
394
|
/* @__PURE__ */ h("button", {
|
|
395
395
|
type: "button",
|
|
396
396
|
onClick: () => P && Q(`/transactions/${P.id}`),
|
|
397
397
|
disabled: !P,
|
|
398
|
-
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-
|
|
398
|
+
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-text-primary hover:bg-bg-sunken rounded-button transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
399
399
|
children: [/* @__PURE__ */ m("div", {
|
|
400
|
-
className: "size-
|
|
401
|
-
children: /* @__PURE__ */ m(Se, { className: "size-4 text-
|
|
400
|
+
className: "size-9 rounded-lg bg-status-info-bg-subtle flex items-center justify-center",
|
|
401
|
+
children: /* @__PURE__ */ m(Se, { className: "size-4 text-status-info-text" })
|
|
402
402
|
}), "View Transactions"]
|
|
403
403
|
}),
|
|
404
404
|
/* @__PURE__ */ h("button", {
|
|
405
405
|
type: "button",
|
|
406
406
|
onClick: () => P && Q(`/creditTransactions/${P.id}`),
|
|
407
407
|
disabled: !P,
|
|
408
|
-
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-
|
|
408
|
+
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-text-primary hover:bg-bg-sunken rounded-button transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
409
409
|
children: [/* @__PURE__ */ m("div", {
|
|
410
|
-
className: "size-
|
|
410
|
+
className: "size-9 rounded-lg bg-status-warning-bg-subtle flex items-center justify-center",
|
|
411
411
|
children: /* @__PURE__ */ m(f, { className: "size-4 text-status-warning-text" })
|
|
412
412
|
}), "Credit History"]
|
|
413
413
|
}),
|
|
414
414
|
/* @__PURE__ */ h("button", {
|
|
415
415
|
type: "button",
|
|
416
416
|
onClick: () => Q("/checkout/credits"),
|
|
417
|
-
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-
|
|
417
|
+
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-text-primary hover:bg-bg-sunken rounded-button transition-colors",
|
|
418
418
|
children: [/* @__PURE__ */ m("div", {
|
|
419
|
-
className: "size-
|
|
419
|
+
className: "size-9 rounded-lg bg-status-success-bg-subtle flex items-center justify-center",
|
|
420
420
|
children: /* @__PURE__ */ m(be, { className: "size-4 text-status-success-text" })
|
|
421
421
|
}), "Purchase Credits"]
|
|
422
422
|
}),
|
|
@@ -424,32 +424,32 @@ var g = () => {
|
|
|
424
424
|
type: "button",
|
|
425
425
|
onClick: () => P && Q(`/usage?billingAccountId=${P.id}`),
|
|
426
426
|
disabled: !P,
|
|
427
|
-
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-
|
|
427
|
+
className: "w-full flex items-center gap-3 px-3 py-2.5 text-sm text-left text-text-primary hover:bg-bg-sunken rounded-button transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
428
428
|
children: [/* @__PURE__ */ m("div", {
|
|
429
|
-
className: "size-
|
|
430
|
-
children: /* @__PURE__ */ m(ge, { className: "size-4 text-
|
|
429
|
+
className: "size-9 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
|
|
430
|
+
children: /* @__PURE__ */ m(ge, { className: "size-4 text-text-link" })
|
|
431
431
|
}), "Usage Analytics"]
|
|
432
432
|
})
|
|
433
433
|
]
|
|
434
434
|
})]
|
|
435
435
|
}), !L && /* @__PURE__ */ h("section", {
|
|
436
|
-
className: "border border-border rounded-
|
|
436
|
+
className: "border border-border-subtle rounded-card bg-[var(--color-accent-soft)] shadow-elevation-1 p-5",
|
|
437
437
|
children: [/* @__PURE__ */ h("div", {
|
|
438
438
|
className: "flex items-start gap-3 mb-4",
|
|
439
439
|
children: [/* @__PURE__ */ m("div", {
|
|
440
|
-
className: "size-10 rounded-lg bg-
|
|
441
|
-
children: /* @__PURE__ */ m(Ce, { className: "size-5 text-
|
|
440
|
+
className: "size-10 rounded-lg bg-bg-surface flex items-center justify-center flex-shrink-0 shadow-elevation-1",
|
|
441
|
+
children: /* @__PURE__ */ m(Ce, { className: "size-5 text-text-link" })
|
|
442
442
|
}), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h3", {
|
|
443
|
-
className: "font-semibold text-
|
|
443
|
+
className: "font-semibold text-text-primary",
|
|
444
444
|
children: "Get Started"
|
|
445
445
|
}), /* @__PURE__ */ m("p", {
|
|
446
|
-
className: "text-sm text-
|
|
446
|
+
className: "text-sm text-text-secondary mt-1",
|
|
447
447
|
children: "Choose a plan that fits your needs to unlock all features"
|
|
448
448
|
})] })]
|
|
449
449
|
}), /* @__PURE__ */ h("button", {
|
|
450
450
|
type: "button",
|
|
451
451
|
onClick: () => Q("/plans"),
|
|
452
|
-
className: "w-full flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-primary-
|
|
452
|
+
className: "w-full flex items-center justify-center gap-2 px-4 py-2.5 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-button hover:bg-action-primary-bgHover transition-colors duration-200",
|
|
453
453
|
children: ["Browse Plans", /* @__PURE__ */ m(_e, { className: "size-4" })]
|
|
454
454
|
})]
|
|
455
455
|
})]
|