@burdenoff/microfe-billing 2026.623.2 → 2026.624.1
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/BillingUserRoutes.js +3 -3
- package/dist/billing/BillingUserRoutes.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +34 -34
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +94 -94
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +40 -40
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +10 -10
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/TransactionsPage.js +62 -62
- package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +7 -7
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
- package/dist/billing/modules/earnings/pages/EarningsPage.js +21 -21
- package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +4 -4
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutsPage.js +33 -33
- package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +4 -4
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js +146 -142
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +4 -4
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/SettingsPage.js +57 -57
- package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +33 -33
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
- package/dist/billing/shared/components/AccessDenied.js +4 -4
- package/dist/billing/shared/components/AccessDenied.js.map +1 -1
- package/dist/billing/shared/components/ActorIdentity.js +8 -8
- package/dist/billing/shared/components/ActorIdentity.js.map +1 -1
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js +11 -11
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js.map +1 -1
- package/dist/billing/shared/ui/Card.js +1 -1
- package/dist/billing/shared/ui/Card.js.map +1 -1
- package/dist/billing/shared/ui/MetricCard.js +1 -1
- package/dist/billing/shared/ui/MetricCard.js.map +1 -1
- package/package.json +1 -1
|
@@ -31,12 +31,12 @@ function V({ title: e, featureFlag: t }) {
|
|
|
31
31
|
return /* @__PURE__ */ m("div", {
|
|
32
32
|
className: "flex min-h-[400px] items-center justify-center p-6",
|
|
33
33
|
children: /* @__PURE__ */ h("div", {
|
|
34
|
-
className: "max-w-md rounded-lg border border-border bg-
|
|
34
|
+
className: "max-w-md rounded-lg border border-border-subtle bg-bg-surface p-6 text-center shadow-sm",
|
|
35
35
|
children: [/* @__PURE__ */ h("h2", {
|
|
36
|
-
className: "text-lg font-semibold text-
|
|
36
|
+
className: "text-lg font-semibold text-text-primary",
|
|
37
37
|
children: [e, " is not enabled"]
|
|
38
38
|
}), /* @__PURE__ */ h("p", {
|
|
39
|
-
className: "mt-2 text-sm text-
|
|
39
|
+
className: "mt-2 text-sm text-text-secondary",
|
|
40
40
|
children: [
|
|
41
41
|
"Ask an administrator to enable the ",
|
|
42
42
|
/* @__PURE__ */ m("span", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BillingUserRoutes.js","names":[],"sources":["../../src/billing/BillingUserRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, type ReactNode } from 'react';\nimport { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AccessDenied } from './shared/components';\nimport { useBillingEventEmitter, type BillingDomainEvent } from './hooks/useBillingEventEmitter';\nimport { useBillingPermissions } from './hooks/useBillingPermissions';\nimport { useBilling } from './providers/BillingProvider';\n\n// Eager load - main entry point\nimport { OverviewPage } from './modules/dashboard';\n\n// Lazy loaded pages - Subscriptions\nconst SubscriptionsListPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.SubscriptionsListPage }))\n);\nconst SubscriptionDetailPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.SubscriptionDetailPage }))\n);\nconst UpgradeSubscriptionPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.UpgradeSubscriptionPage }))\n);\n\n// Lazy loaded pages - Plans (user browse pages, no create/edit/toggle)\nconst PlansBrowsePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlansBrowsePage }))\n);\nconst PlanBrowseDetailPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanBrowseDetailPage }))\n);\n\n// Lazy loaded pages - Addons (user browse pages, no create/edit/toggle)\nconst AddonsBrowsePage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonsBrowsePage }))\n);\nconst AddonBrowseDetailPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonBrowseDetailPage }))\n);\n\n// Lazy loaded pages - Billing (Invoices, Transactions, Payments, Refunds)\nconst InvoicesListPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.InvoicesListPage }))\n);\nconst InvoiceDetailPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.InvoiceDetailPage }))\n);\nconst TransactionsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.TransactionsPage }))\n);\nconst UserRefundsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.UserRefundsPage }))\n);\nconst PaymentMethodsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.PaymentMethodsPage }))\n);\n\n// Lazy loaded pages - Credits\nconst CreditsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditsPage }))\n);\nconst CreditTransactionsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditTransactionsPage }))\n);\nconst CreditWithdrawalPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditWithdrawalPage }))\n);\n\n// Lazy loaded pages - Usage\nconst UsagePage = lazy(() => import('./modules/usage').then((m) => ({ default: m.UsagePage })));\n\n// Lazy loaded pages - Checkout\nconst CheckoutPage = lazy(() =>\n import('./modules/checkout').then((m) => ({ default: m.CheckoutPage }))\n);\n\n// Lazy loaded pages - Store\nconst StoreCheckoutPage = lazy(() =>\n import('./modules/store').then((m) => ({ default: m.StoreCheckoutPage }))\n);\n\n// Lazy loaded pages - Settings\nconst SettingsPage = lazy(() =>\n import('./modules/settings').then((m) => ({ default: m.SettingsPage }))\n);\nconst TeamPermissionsPage = lazy(() =>\n import('./modules/settings').then((m) => ({ default: m.TeamPermissionsPage }))\n);\nconst AffiliateDashboardPage = lazy(() =>\n import('./modules/affiliate').then((m) => ({ default: m.AffiliateDashboardPage }))\n);\nconst EarningsPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.EarningsPage }))\n);\nconst PayoutsPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.PayoutsPage }))\n);\n\nfunction PageLoader() {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"size-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\nfunction DefaultRedirect() {\n const { basePath } = useBilling();\n const { search } = useLocation();\n const routerNavigate = useNavigate();\n const base = basePath && basePath !== '/' ? basePath.replace(/\\/$/, '') : '';\n useEffect(() => {\n routerNavigate(`${base}/overview${search}`, { replace: true });\n }, [base, routerNavigate, search]);\n return null;\n}\n\ntype BillingPermissions = ReturnType<typeof useBillingPermissions>;\ntype BillingPermissionKey = Exclude<\n {\n [K in keyof BillingPermissions]: BillingPermissions[K] extends boolean ? K : never;\n }[keyof BillingPermissions],\n 'isLoading'\n>;\n\ninterface BillingRouteGateProps {\n title: string;\n featureFlag: string;\n permission: BillingPermissionKey;\n eventName: BillingDomainEvent;\n children: ReactNode;\n}\n\nfunction FeatureDisabled({ title, featureFlag }: { title: string; featureFlag: string }) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center p-6\">\n <div className=\"max-w-md rounded-lg border border-border bg-card p-6 text-center shadow-sm\">\n <h2 className=\"text-lg font-semibold text-foreground\">{title} is not enabled</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Ask an administrator to enable the <span className=\"font-mono\">{featureFlag}</span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\nfunction BillingRouteGate({\n title,\n featureFlag,\n permission,\n eventName,\n children,\n}: BillingRouteGateProps) {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const hasPermission = Boolean(permissions[permission]);\n\n useEffect(() => {\n if (hasPermission) {\n emit(eventName, { source: 'BillingUserRoutes' });\n }\n }, [emit, eventName, hasPermission]);\n\n if (permissions.isLoading) {\n return <PageLoader />;\n }\n\n return (\n <FeatureGate\n flag={featureFlag}\n defaultValue\n fallback={<FeatureDisabled title={title} featureFlag={featureFlag} />}\n >\n {hasPermission ? (\n children\n ) : (\n <AccessDenied message={`You don't have permission to access ${title}.`} />\n )}\n </FeatureGate>\n );\n}\n\nfunction guardedPage(props: BillingRouteGateProps): ReactNode {\n return <BillingRouteGate {...props} />;\n}\n\n/**\n * User-facing billing routes.\n * Includes overview, subscriptions, plan/addon browsing (read-only),\n * invoices, payments, credits, quota usage, checkout, and settings.\n */\nexport function BillingUserRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"overview\" replace />} />\n\n {/* Dashboard */}\n <Route\n path=\"overview\"\n element={guardedPage({\n title: 'Billing overview',\n featureFlag: 'billing.overview',\n permission: 'canViewBillingAccount',\n eventName: 'billing.billing_account.viewed',\n children: <OverviewPage />,\n })}\n />\n\n {/* Subscriptions */}\n <Route\n path=\"subscriptions\"\n element={\n <BillingRouteGate\n title=\"Subscriptions\"\n featureFlag=\"billing.subscriptions\"\n permission=\"canViewSubscriptions\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SubscriptionsListPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"subscriptions/:subscriptionId\"\n element={\n <BillingRouteGate\n title=\"Subscription details\"\n featureFlag=\"billing.subscriptions\"\n permission=\"canViewSubscriptions\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SubscriptionDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"subscriptions/:subscriptionId/upgrade\"\n element={\n <BillingRouteGate\n title=\"Subscription upgrade\"\n featureFlag=\"billing.subscriptions.upgrade\"\n permission=\"canCreateSubscription\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UpgradeSubscriptionPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Plans - user browse pages */}\n <Route\n path=\"plans\"\n element={\n <BillingRouteGate\n title=\"Plans\"\n featureFlag=\"billing.plans\"\n permission=\"canViewPlans\"\n eventName=\"billing.plan.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PlansBrowsePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"plans/:planId\"\n element={\n <BillingRouteGate\n title=\"Plan details\"\n featureFlag=\"billing.plans\"\n permission=\"canViewPlans\"\n eventName=\"billing.plan.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PlanBrowseDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Addons - user browse pages */}\n <Route\n path=\"addons\"\n element={\n <BillingRouteGate\n title=\"Addons\"\n featureFlag=\"billing.addons\"\n permission=\"canViewAddons\"\n eventName=\"billing.addon.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AddonsBrowsePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"addons/:addonId\"\n element={\n <BillingRouteGate\n title=\"Addon details\"\n featureFlag=\"billing.addons\"\n permission=\"canViewAddons\"\n eventName=\"billing.addon.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AddonBrowseDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Checkout */}\n <Route\n path=\"checkout\"\n element={\n <BillingRouteGate\n title=\"Checkout\"\n featureFlag=\"billing.checkout\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/:planId\"\n element={\n <BillingRouteGate\n title=\"Plan checkout\"\n featureFlag=\"billing.checkout\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/credits\"\n element={\n <BillingRouteGate\n title=\"Credits checkout\"\n featureFlag=\"billing.checkout.credits\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/addon/:addonId\"\n element={\n <BillingRouteGate\n title=\"Addon checkout\"\n featureFlag=\"billing.checkout.addons\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/addons\"\n element={\n <BillingRouteGate\n title=\"Addons checkout\"\n featureFlag=\"billing.checkout.addons\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/store/:storeOrderId\"\n element={\n <BillingRouteGate\n title=\"Store order checkout\"\n featureFlag=\"billing.checkout.store\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Store Checkout - Legacy */}\n <Route\n path=\"store/:orderId\"\n element={\n <BillingRouteGate\n title=\"Store checkout\"\n featureFlag=\"billing.checkout.store\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <StoreCheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Refunds — user-facing request + history */}\n <Route\n path=\"refunds\"\n element={\n <BillingRouteGate\n title=\"Refunds\"\n featureFlag=\"billing.transactions\"\n permission=\"canViewPayments\"\n eventName=\"billing.transaction.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UserRefundsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Invoices */}\n <Route\n path=\"invoices\"\n element={\n <BillingRouteGate\n title=\"Invoices\"\n featureFlag=\"billing.invoices\"\n permission=\"canViewInvoices\"\n eventName=\"billing.invoice.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <InvoicesListPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"invoices/:invoiceId\"\n element={\n <BillingRouteGate\n title=\"Invoice details\"\n featureFlag=\"billing.invoices\"\n permission=\"canViewInvoices\"\n eventName=\"billing.invoice.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <InvoiceDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Payment Methods */}\n <Route\n path=\"payment-methods\"\n element={\n <BillingRouteGate\n title=\"Payment methods\"\n featureFlag=\"billing.payment_methods\"\n permission=\"canViewPaymentMethods\"\n eventName=\"billing.payment_method.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PaymentMethodsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"payment-methods/add\"\n element={\n <BillingRouteGate\n title=\"Add payment method\"\n featureFlag=\"billing.payment_methods\"\n permission=\"canManagePaymentMethods\"\n eventName=\"billing.payment_method.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PaymentMethodsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Credits */}\n <Route\n path=\"credits\"\n element={\n <BillingRouteGate\n title=\"Credits\"\n featureFlag=\"billing.credits\"\n permission=\"canViewCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"credits/withdraw\"\n element={\n <BillingRouteGate\n title=\"Credit withdrawal\"\n featureFlag=\"billing.credits\"\n permission=\"canWithdrawCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditWithdrawalPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"creditTransactions/:billingAccountId\"\n element={\n <BillingRouteGate\n title=\"Credit transactions\"\n featureFlag=\"billing.credits\"\n permission=\"canViewCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditTransactionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Usage */}\n <Route\n path=\"usage\"\n element={\n <BillingRouteGate\n title=\"Usage\"\n featureFlag=\"billing.usage\"\n permission=\"canViewUsage\"\n eventName=\"billing.usage.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UsagePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"affiliate\"\n element={\n <BillingRouteGate\n title=\"Affiliate dashboard\"\n featureFlag=\"billing.affiliate\"\n permission=\"canManagePaymentMethods\"\n eventName=\"billing.affiliate.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AffiliateDashboardPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"earnings\"\n element={\n <BillingRouteGate\n title=\"Earnings\"\n featureFlag=\"billing.earnings\"\n permission=\"canViewBillingAccount\"\n eventName=\"billing.earning.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <EarningsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"payouts\"\n element={\n <BillingRouteGate\n title=\"Payouts\"\n featureFlag=\"billing.payouts\"\n permission=\"canViewBillingAccount\"\n eventName=\"billing.payout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PayoutsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Transaction History */}\n <Route\n path=\"transactions/:billingAccountId\"\n element={\n <BillingRouteGate\n title=\"Transactions\"\n featureFlag=\"billing.transactions\"\n permission=\"canViewPayments\"\n eventName=\"billing.transaction.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <TransactionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={\n <BillingRouteGate\n title=\"Billing settings\"\n featureFlag=\"billing.settings\"\n permission=\"canManageBillingAccount\"\n eventName=\"billing.billing_account.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SettingsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Team & Permissions — billing-scope role assignments.\n * Gated on `isBillingAdmin` (billing:manage), not the broader\n * `canManageBillingAccount` (billing:update), because role\n * assignment is a privilege-escalation surface and the server-side\n * RBAC contract reserves it for Billing Admins only. */}\n <Route\n path=\"team-permissions\"\n element={\n <BillingRouteGate\n title=\"Team & Permissions\"\n featureFlag=\"billing.team_permissions\"\n permission=\"isBillingAdmin\"\n eventName=\"billing.billing_account.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <TeamPermissionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Catch-all */}\n <Route path=\"*\" element={<DefaultRedirect />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BillingUserRoutes.js","names":[],"sources":["../../src/billing/BillingUserRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, type ReactNode } from 'react';\nimport { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { AccessDenied } from './shared/components';\nimport { useBillingEventEmitter, type BillingDomainEvent } from './hooks/useBillingEventEmitter';\nimport { useBillingPermissions } from './hooks/useBillingPermissions';\nimport { useBilling } from './providers/BillingProvider';\n\n// Eager load - main entry point\nimport { OverviewPage } from './modules/dashboard';\n\n// Lazy loaded pages - Subscriptions\nconst SubscriptionsListPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.SubscriptionsListPage }))\n);\nconst SubscriptionDetailPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.SubscriptionDetailPage }))\n);\nconst UpgradeSubscriptionPage = lazy(() =>\n import('./modules/subscriptions').then((m) => ({ default: m.UpgradeSubscriptionPage }))\n);\n\n// Lazy loaded pages - Plans (user browse pages, no create/edit/toggle)\nconst PlansBrowsePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlansBrowsePage }))\n);\nconst PlanBrowseDetailPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanBrowseDetailPage }))\n);\n\n// Lazy loaded pages - Addons (user browse pages, no create/edit/toggle)\nconst AddonsBrowsePage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonsBrowsePage }))\n);\nconst AddonBrowseDetailPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonBrowseDetailPage }))\n);\n\n// Lazy loaded pages - Billing (Invoices, Transactions, Payments, Refunds)\nconst InvoicesListPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.InvoicesListPage }))\n);\nconst InvoiceDetailPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.InvoiceDetailPage }))\n);\nconst TransactionsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.TransactionsPage }))\n);\nconst UserRefundsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.UserRefundsPage }))\n);\nconst PaymentMethodsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.PaymentMethodsPage }))\n);\n\n// Lazy loaded pages - Credits\nconst CreditsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditsPage }))\n);\nconst CreditTransactionsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditTransactionsPage }))\n);\nconst CreditWithdrawalPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.CreditWithdrawalPage }))\n);\n\n// Lazy loaded pages - Usage\nconst UsagePage = lazy(() => import('./modules/usage').then((m) => ({ default: m.UsagePage })));\n\n// Lazy loaded pages - Checkout\nconst CheckoutPage = lazy(() =>\n import('./modules/checkout').then((m) => ({ default: m.CheckoutPage }))\n);\n\n// Lazy loaded pages - Store\nconst StoreCheckoutPage = lazy(() =>\n import('./modules/store').then((m) => ({ default: m.StoreCheckoutPage }))\n);\n\n// Lazy loaded pages - Settings\nconst SettingsPage = lazy(() =>\n import('./modules/settings').then((m) => ({ default: m.SettingsPage }))\n);\nconst TeamPermissionsPage = lazy(() =>\n import('./modules/settings').then((m) => ({ default: m.TeamPermissionsPage }))\n);\nconst AffiliateDashboardPage = lazy(() =>\n import('./modules/affiliate').then((m) => ({ default: m.AffiliateDashboardPage }))\n);\nconst EarningsPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.EarningsPage }))\n);\nconst PayoutsPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.PayoutsPage }))\n);\n\nfunction PageLoader() {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <div className=\"size-8 animate-spin rounded-full border-4 border-primary border-t-transparent\" />\n </div>\n );\n}\n\nfunction DefaultRedirect() {\n const { basePath } = useBilling();\n const { search } = useLocation();\n const routerNavigate = useNavigate();\n const base = basePath && basePath !== '/' ? basePath.replace(/\\/$/, '') : '';\n useEffect(() => {\n routerNavigate(`${base}/overview${search}`, { replace: true });\n }, [base, routerNavigate, search]);\n return null;\n}\n\ntype BillingPermissions = ReturnType<typeof useBillingPermissions>;\ntype BillingPermissionKey = Exclude<\n {\n [K in keyof BillingPermissions]: BillingPermissions[K] extends boolean ? K : never;\n }[keyof BillingPermissions],\n 'isLoading'\n>;\n\ninterface BillingRouteGateProps {\n title: string;\n featureFlag: string;\n permission: BillingPermissionKey;\n eventName: BillingDomainEvent;\n children: ReactNode;\n}\n\nfunction FeatureDisabled({ title, featureFlag }: { title: string; featureFlag: string }) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center p-6\">\n <div className=\"max-w-md rounded-lg border border-border-subtle bg-bg-surface p-6 text-center shadow-sm\">\n <h2 className=\"text-lg font-semibold text-text-primary\">{title} is not enabled</h2>\n <p className=\"mt-2 text-sm text-text-secondary\">\n Ask an administrator to enable the <span className=\"font-mono\">{featureFlag}</span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\nfunction BillingRouteGate({\n title,\n featureFlag,\n permission,\n eventName,\n children,\n}: BillingRouteGateProps) {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const hasPermission = Boolean(permissions[permission]);\n\n useEffect(() => {\n if (hasPermission) {\n emit(eventName, { source: 'BillingUserRoutes' });\n }\n }, [emit, eventName, hasPermission]);\n\n if (permissions.isLoading) {\n return <PageLoader />;\n }\n\n return (\n <FeatureGate\n flag={featureFlag}\n defaultValue\n fallback={<FeatureDisabled title={title} featureFlag={featureFlag} />}\n >\n {hasPermission ? (\n children\n ) : (\n <AccessDenied message={`You don't have permission to access ${title}.`} />\n )}\n </FeatureGate>\n );\n}\n\nfunction guardedPage(props: BillingRouteGateProps): ReactNode {\n return <BillingRouteGate {...props} />;\n}\n\n/**\n * User-facing billing routes.\n * Includes overview, subscriptions, plan/addon browsing (read-only),\n * invoices, payments, credits, quota usage, checkout, and settings.\n */\nexport function BillingUserRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"overview\" replace />} />\n\n {/* Dashboard */}\n <Route\n path=\"overview\"\n element={guardedPage({\n title: 'Billing overview',\n featureFlag: 'billing.overview',\n permission: 'canViewBillingAccount',\n eventName: 'billing.billing_account.viewed',\n children: <OverviewPage />,\n })}\n />\n\n {/* Subscriptions */}\n <Route\n path=\"subscriptions\"\n element={\n <BillingRouteGate\n title=\"Subscriptions\"\n featureFlag=\"billing.subscriptions\"\n permission=\"canViewSubscriptions\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SubscriptionsListPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"subscriptions/:subscriptionId\"\n element={\n <BillingRouteGate\n title=\"Subscription details\"\n featureFlag=\"billing.subscriptions\"\n permission=\"canViewSubscriptions\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SubscriptionDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"subscriptions/:subscriptionId/upgrade\"\n element={\n <BillingRouteGate\n title=\"Subscription upgrade\"\n featureFlag=\"billing.subscriptions.upgrade\"\n permission=\"canCreateSubscription\"\n eventName=\"billing.subscription.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UpgradeSubscriptionPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Plans - user browse pages */}\n <Route\n path=\"plans\"\n element={\n <BillingRouteGate\n title=\"Plans\"\n featureFlag=\"billing.plans\"\n permission=\"canViewPlans\"\n eventName=\"billing.plan.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PlansBrowsePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"plans/:planId\"\n element={\n <BillingRouteGate\n title=\"Plan details\"\n featureFlag=\"billing.plans\"\n permission=\"canViewPlans\"\n eventName=\"billing.plan.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PlanBrowseDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Addons - user browse pages */}\n <Route\n path=\"addons\"\n element={\n <BillingRouteGate\n title=\"Addons\"\n featureFlag=\"billing.addons\"\n permission=\"canViewAddons\"\n eventName=\"billing.addon.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AddonsBrowsePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"addons/:addonId\"\n element={\n <BillingRouteGate\n title=\"Addon details\"\n featureFlag=\"billing.addons\"\n permission=\"canViewAddons\"\n eventName=\"billing.addon.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AddonBrowseDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Checkout */}\n <Route\n path=\"checkout\"\n element={\n <BillingRouteGate\n title=\"Checkout\"\n featureFlag=\"billing.checkout\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/:planId\"\n element={\n <BillingRouteGate\n title=\"Plan checkout\"\n featureFlag=\"billing.checkout\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/credits\"\n element={\n <BillingRouteGate\n title=\"Credits checkout\"\n featureFlag=\"billing.checkout.credits\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/addon/:addonId\"\n element={\n <BillingRouteGate\n title=\"Addon checkout\"\n featureFlag=\"billing.checkout.addons\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/addons\"\n element={\n <BillingRouteGate\n title=\"Addons checkout\"\n featureFlag=\"billing.checkout.addons\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"checkout/store/:storeOrderId\"\n element={\n <BillingRouteGate\n title=\"Store order checkout\"\n featureFlag=\"billing.checkout.store\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Store Checkout - Legacy */}\n <Route\n path=\"store/:orderId\"\n element={\n <BillingRouteGate\n title=\"Store checkout\"\n featureFlag=\"billing.checkout.store\"\n permission=\"canProcessPayment\"\n eventName=\"billing.checkout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <StoreCheckoutPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Refunds — user-facing request + history */}\n <Route\n path=\"refunds\"\n element={\n <BillingRouteGate\n title=\"Refunds\"\n featureFlag=\"billing.transactions\"\n permission=\"canViewPayments\"\n eventName=\"billing.transaction.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UserRefundsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Invoices */}\n <Route\n path=\"invoices\"\n element={\n <BillingRouteGate\n title=\"Invoices\"\n featureFlag=\"billing.invoices\"\n permission=\"canViewInvoices\"\n eventName=\"billing.invoice.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <InvoicesListPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"invoices/:invoiceId\"\n element={\n <BillingRouteGate\n title=\"Invoice details\"\n featureFlag=\"billing.invoices\"\n permission=\"canViewInvoices\"\n eventName=\"billing.invoice.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <InvoiceDetailPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Payment Methods */}\n <Route\n path=\"payment-methods\"\n element={\n <BillingRouteGate\n title=\"Payment methods\"\n featureFlag=\"billing.payment_methods\"\n permission=\"canViewPaymentMethods\"\n eventName=\"billing.payment_method.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PaymentMethodsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"payment-methods/add\"\n element={\n <BillingRouteGate\n title=\"Add payment method\"\n featureFlag=\"billing.payment_methods\"\n permission=\"canManagePaymentMethods\"\n eventName=\"billing.payment_method.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PaymentMethodsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Credits */}\n <Route\n path=\"credits\"\n element={\n <BillingRouteGate\n title=\"Credits\"\n featureFlag=\"billing.credits\"\n permission=\"canViewCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"credits/withdraw\"\n element={\n <BillingRouteGate\n title=\"Credit withdrawal\"\n featureFlag=\"billing.credits\"\n permission=\"canWithdrawCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditWithdrawalPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n <Route\n path=\"creditTransactions/:billingAccountId\"\n element={\n <BillingRouteGate\n title=\"Credit transactions\"\n featureFlag=\"billing.credits\"\n permission=\"canViewCredits\"\n eventName=\"billing.credit.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <CreditTransactionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Usage */}\n <Route\n path=\"usage\"\n element={\n <BillingRouteGate\n title=\"Usage\"\n featureFlag=\"billing.usage\"\n permission=\"canViewUsage\"\n eventName=\"billing.usage.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <UsagePage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"affiliate\"\n element={\n <BillingRouteGate\n title=\"Affiliate dashboard\"\n featureFlag=\"billing.affiliate\"\n permission=\"canManagePaymentMethods\"\n eventName=\"billing.affiliate.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <AffiliateDashboardPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"earnings\"\n element={\n <BillingRouteGate\n title=\"Earnings\"\n featureFlag=\"billing.earnings\"\n permission=\"canViewBillingAccount\"\n eventName=\"billing.earning.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <EarningsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n <Route\n path=\"payouts\"\n element={\n <BillingRouteGate\n title=\"Payouts\"\n featureFlag=\"billing.payouts\"\n permission=\"canViewBillingAccount\"\n eventName=\"billing.payout.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <PayoutsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Transaction History */}\n <Route\n path=\"transactions/:billingAccountId\"\n element={\n <BillingRouteGate\n title=\"Transactions\"\n featureFlag=\"billing.transactions\"\n permission=\"canViewPayments\"\n eventName=\"billing.transaction.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <TransactionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Settings */}\n <Route\n path=\"settings\"\n element={\n <BillingRouteGate\n title=\"Billing settings\"\n featureFlag=\"billing.settings\"\n permission=\"canManageBillingAccount\"\n eventName=\"billing.billing_account.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <SettingsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Team & Permissions — billing-scope role assignments.\n * Gated on `isBillingAdmin` (billing:manage), not the broader\n * `canManageBillingAccount` (billing:update), because role\n * assignment is a privilege-escalation surface and the server-side\n * RBAC contract reserves it for Billing Admins only. */}\n <Route\n path=\"team-permissions\"\n element={\n <BillingRouteGate\n title=\"Team & Permissions\"\n featureFlag=\"billing.team_permissions\"\n permission=\"isBillingAdmin\"\n eventName=\"billing.billing_account.viewed\"\n >\n <Suspense fallback={<PageLoader />}>\n <TeamPermissionsPage />\n </Suspense>\n </BillingRouteGate>\n }\n />\n\n {/* Catch-all */}\n <Route path=\"*\" element={<DefaultRedirect />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ var y = () => {
|
|
|
35
35
|
}, { addonId: x } = m(), S = s(), { addon: C, isLoading: w, error: T, refetch: E } = c(x), { addToCart: D, removeFromCart: O, updateQuantity: k, isInCart: A, getCartItem: j } = o(), M = l(() => v(C?.features || []), [C?.features]), N = C ? A(C.id) : !1, P = (C ? j(C.id) : void 0)?.quantity || 0;
|
|
36
36
|
return w ? /* @__PURE__ */ g("div", {
|
|
37
37
|
className: "space-y-6 p-6",
|
|
38
|
-
children: [/* @__PURE__ */ h("div", { className: "h-8 w-48 bg-
|
|
38
|
+
children: [/* @__PURE__ */ h("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ g("div", {
|
|
39
39
|
className: "grid grid-cols-1 lg:grid-cols-3 gap-6",
|
|
40
40
|
children: [/* @__PURE__ */ h("div", {
|
|
41
41
|
className: "lg:col-span-2 space-y-4",
|
|
@@ -43,8 +43,8 @@ var y = () => {
|
|
|
43
43
|
1,
|
|
44
44
|
2,
|
|
45
45
|
3
|
|
46
|
-
].map((e) => /* @__PURE__ */ h("div", { className: "h-24 bg-
|
|
47
|
-
}), /* @__PURE__ */ h("div", { className: "h-64 bg-
|
|
46
|
+
].map((e) => /* @__PURE__ */ h("div", { className: "h-24 bg-bg-sunken animate-pulse rounded" }, e))
|
|
47
|
+
}), /* @__PURE__ */ h("div", { className: "h-64 bg-bg-sunken animate-pulse rounded" })]
|
|
48
48
|
})]
|
|
49
49
|
}) : T && a(T) ? /* @__PURE__ */ h("div", {
|
|
50
50
|
className: "p-6",
|
|
@@ -64,11 +64,11 @@ var y = () => {
|
|
|
64
64
|
children: [/* @__PURE__ */ g("div", {
|
|
65
65
|
className: "lg:col-span-2 space-y-6",
|
|
66
66
|
children: [/* @__PURE__ */ g("div", {
|
|
67
|
-
className: "border border-border rounded-lg bg-
|
|
67
|
+
className: "border border-border-subtle rounded-lg bg-bg-surface overflow-hidden",
|
|
68
68
|
children: [/* @__PURE__ */ h("div", {
|
|
69
|
-
className: "p-4 border-b border-border bg-
|
|
69
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
70
70
|
children: /* @__PURE__ */ h("h2", {
|
|
71
|
-
className: "font-semibold text-
|
|
71
|
+
className: "font-semibold text-text-primary",
|
|
72
72
|
children: b("billing.addons.pricing", "Pricing")
|
|
73
73
|
})
|
|
74
74
|
}), /* @__PURE__ */ g("div", {
|
|
@@ -76,14 +76,14 @@ var y = () => {
|
|
|
76
76
|
children: [/* @__PURE__ */ g("div", {
|
|
77
77
|
className: "flex items-baseline gap-2",
|
|
78
78
|
children: [/* @__PURE__ */ h("span", {
|
|
79
|
-
className: "text-4xl font-bold text-
|
|
79
|
+
className: "text-4xl font-bold text-text-primary",
|
|
80
80
|
children: n(C.price, C.currency)
|
|
81
81
|
}), /* @__PURE__ */ g("span", {
|
|
82
|
-
className: "text-lg text-
|
|
82
|
+
className: "text-lg text-text-secondary",
|
|
83
83
|
children: ["/ ", r(C.duration)]
|
|
84
84
|
})]
|
|
85
85
|
}), /* @__PURE__ */ g("p", {
|
|
86
|
-
className: "text-sm text-
|
|
86
|
+
className: "text-sm text-text-secondary mt-2",
|
|
87
87
|
children: [
|
|
88
88
|
b("billing.addons.billed", "Billed"),
|
|
89
89
|
" ",
|
|
@@ -92,11 +92,11 @@ var y = () => {
|
|
|
92
92
|
})]
|
|
93
93
|
})]
|
|
94
94
|
}), /* @__PURE__ */ g("div", {
|
|
95
|
-
className: "border border-border rounded-lg bg-
|
|
95
|
+
className: "border border-border-subtle rounded-lg bg-bg-surface overflow-hidden",
|
|
96
96
|
children: [/* @__PURE__ */ h("div", {
|
|
97
|
-
className: "p-4 border-b border-border bg-
|
|
97
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
98
98
|
children: /* @__PURE__ */ g("h2", {
|
|
99
|
-
className: "font-semibold text-
|
|
99
|
+
className: "font-semibold text-text-primary",
|
|
100
100
|
children: [
|
|
101
101
|
b("billing.addons.includedQuotas", "Included Quotas"),
|
|
102
102
|
" (",
|
|
@@ -107,16 +107,16 @@ var y = () => {
|
|
|
107
107
|
}), /* @__PURE__ */ h("div", {
|
|
108
108
|
className: "p-4",
|
|
109
109
|
children: M.length === 0 ? /* @__PURE__ */ h("p", {
|
|
110
|
-
className: "text-sm text-
|
|
110
|
+
className: "text-sm text-text-secondary py-4 text-center",
|
|
111
111
|
children: b("billing.addons.noQuotas", "No quotas associated with this addon.")
|
|
112
112
|
}) : /* @__PURE__ */ h("div", {
|
|
113
113
|
className: "space-y-3",
|
|
114
114
|
children: M.map((e) => /* @__PURE__ */ g("div", {
|
|
115
|
-
className: "flex items-center justify-between p-3 border border-border rounded-lg bg-
|
|
115
|
+
className: "flex items-center justify-between p-3 border border-border-subtle rounded-lg bg-bg-sunken/20",
|
|
116
116
|
children: [/* @__PURE__ */ g("div", {
|
|
117
117
|
className: "flex items-center gap-3",
|
|
118
118
|
children: [/* @__PURE__ */ h("div", {
|
|
119
|
-
className: "size-8 rounded-full bg-primary/10 flex items-center justify-center",
|
|
119
|
+
className: "size-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center",
|
|
120
120
|
children: /* @__PURE__ */ h("svg", {
|
|
121
121
|
className: "size-4 text-primary",
|
|
122
122
|
fill: "none",
|
|
@@ -130,10 +130,10 @@ var y = () => {
|
|
|
130
130
|
})
|
|
131
131
|
})
|
|
132
132
|
}), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ h("p", {
|
|
133
|
-
className: "font-medium text-
|
|
133
|
+
className: "font-medium text-text-primary",
|
|
134
134
|
children: e.name
|
|
135
135
|
}), /* @__PURE__ */ g("p", {
|
|
136
|
-
className: "text-xs text-
|
|
136
|
+
className: "text-xs text-text-secondary capitalize",
|
|
137
137
|
children: ["Type: ", e.type]
|
|
138
138
|
})] })]
|
|
139
139
|
}), /* @__PURE__ */ g("div", {
|
|
@@ -142,7 +142,7 @@ var y = () => {
|
|
|
142
142
|
className: "text-lg font-semibold text-status-success-text",
|
|
143
143
|
children: e.totalValue.toLocaleString()
|
|
144
144
|
}), /* @__PURE__ */ h("p", {
|
|
145
|
-
className: "text-xs text-
|
|
145
|
+
className: "text-xs text-text-secondary",
|
|
146
146
|
children: "total"
|
|
147
147
|
})]
|
|
148
148
|
})]
|
|
@@ -153,11 +153,11 @@ var y = () => {
|
|
|
153
153
|
}), /* @__PURE__ */ g("div", {
|
|
154
154
|
className: "space-y-6",
|
|
155
155
|
children: [/* @__PURE__ */ g("div", {
|
|
156
|
-
className: "border border-border rounded-lg bg-
|
|
156
|
+
className: "border border-border-subtle rounded-lg bg-bg-surface overflow-hidden",
|
|
157
157
|
children: [/* @__PURE__ */ h("div", {
|
|
158
|
-
className: "p-4 border-b border-border bg-
|
|
158
|
+
className: "p-4 border-b border-border-subtle bg-bg-sunken/30",
|
|
159
159
|
children: /* @__PURE__ */ h("h2", {
|
|
160
|
-
className: "font-semibold text-
|
|
160
|
+
className: "font-semibold text-text-primary",
|
|
161
161
|
children: b("billing.addons.purchase", "Purchase")
|
|
162
162
|
})
|
|
163
163
|
}), /* @__PURE__ */ g("div", {
|
|
@@ -166,10 +166,10 @@ var y = () => {
|
|
|
166
166
|
/* @__PURE__ */ g("div", {
|
|
167
167
|
className: "flex items-center justify-between",
|
|
168
168
|
children: [/* @__PURE__ */ h("span", {
|
|
169
|
-
className: "text-sm text-
|
|
169
|
+
className: "text-sm text-text-secondary",
|
|
170
170
|
children: b("billing.addons.price", "Price")
|
|
171
171
|
}), /* @__PURE__ */ g("span", {
|
|
172
|
-
className: "text-sm font-medium text-
|
|
172
|
+
className: "text-sm font-medium text-text-primary",
|
|
173
173
|
children: [
|
|
174
174
|
n(C.price, C.currency),
|
|
175
175
|
" /",
|
|
@@ -181,10 +181,10 @@ var y = () => {
|
|
|
181
181
|
/* @__PURE__ */ g("div", {
|
|
182
182
|
className: "flex items-center justify-between",
|
|
183
183
|
children: [/* @__PURE__ */ h("span", {
|
|
184
|
-
className: "text-sm text-
|
|
184
|
+
className: "text-sm text-text-secondary",
|
|
185
185
|
children: b("billing.addons.billingLabel", "Billing")
|
|
186
186
|
}), /* @__PURE__ */ h("span", {
|
|
187
|
-
className: "text-sm font-medium text-
|
|
187
|
+
className: "text-sm font-medium text-text-primary capitalize",
|
|
188
188
|
children: C.duration
|
|
189
189
|
})]
|
|
190
190
|
}),
|
|
@@ -200,7 +200,7 @@ var y = () => {
|
|
|
200
200
|
/* @__PURE__ */ h("button", {
|
|
201
201
|
type: "button",
|
|
202
202
|
onClick: () => k(C.id, P - 1),
|
|
203
|
-
className: "p-1.5 rounded border border-border hover:bg-
|
|
203
|
+
className: "p-1.5 rounded border border-border-subtle hover:bg-bg-sunken transition-colors",
|
|
204
204
|
children: /* @__PURE__ */ h(u, { className: "size-4" })
|
|
205
205
|
}),
|
|
206
206
|
/* @__PURE__ */ h("span", {
|
|
@@ -210,27 +210,27 @@ var y = () => {
|
|
|
210
210
|
/* @__PURE__ */ h("button", {
|
|
211
211
|
type: "button",
|
|
212
212
|
onClick: () => k(C.id, P + 1),
|
|
213
|
-
className: "p-1.5 rounded border border-border hover:bg-
|
|
213
|
+
className: "p-1.5 rounded border border-border-subtle hover:bg-bg-sunken transition-colors",
|
|
214
214
|
children: /* @__PURE__ */ h(d, { className: "size-4" })
|
|
215
215
|
})
|
|
216
216
|
]
|
|
217
217
|
}), /* @__PURE__ */ h("button", {
|
|
218
218
|
type: "button",
|
|
219
219
|
onClick: () => O(C.id),
|
|
220
|
-
className: "p-1.5 rounded text-
|
|
220
|
+
className: "p-1.5 rounded text-status-error-text hover:bg-status-error-bg/10 transition-colors",
|
|
221
221
|
title: "Remove from cart",
|
|
222
222
|
children: /* @__PURE__ */ h(p, { className: "size-4" })
|
|
223
223
|
})]
|
|
224
224
|
}), /* @__PURE__ */ h("button", {
|
|
225
225
|
type: "button",
|
|
226
226
|
onClick: () => S("/checkout/addons"),
|
|
227
|
-
className: "w-full px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
227
|
+
className: "w-full px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors",
|
|
228
228
|
children: "Proceed to Checkout"
|
|
229
229
|
})]
|
|
230
230
|
}) : /* @__PURE__ */ g("button", {
|
|
231
231
|
type: "button",
|
|
232
232
|
onClick: () => D(C),
|
|
233
|
-
className: "w-full px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
233
|
+
className: "w-full px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors flex items-center justify-center gap-2",
|
|
234
234
|
children: [/* @__PURE__ */ h(f, { className: "size-4" }), "Add to Cart"]
|
|
235
235
|
})
|
|
236
236
|
})
|
|
@@ -239,7 +239,7 @@ var y = () => {
|
|
|
239
239
|
}), /* @__PURE__ */ h("button", {
|
|
240
240
|
type: "button",
|
|
241
241
|
onClick: () => S("/addons"),
|
|
242
|
-
className: "w-full px-4 py-2 text-sm font-medium border border-border text-
|
|
242
|
+
className: "w-full px-4 py-2 text-sm font-medium border border-border-subtle text-text-primary rounded-md hover:bg-bg-sunken transition-colors",
|
|
243
243
|
children: "Back to Addons"
|
|
244
244
|
})]
|
|
245
245
|
})]
|
|
@@ -250,17 +250,17 @@ var y = () => {
|
|
|
250
250
|
className: "text-center space-y-4",
|
|
251
251
|
children: [
|
|
252
252
|
/* @__PURE__ */ h("h2", {
|
|
253
|
-
className: "text-lg font-semibold text-
|
|
253
|
+
className: "text-lg font-semibold text-text-primary",
|
|
254
254
|
children: b("billing.addons.addonNotFound", "Addon not found")
|
|
255
255
|
}),
|
|
256
256
|
/* @__PURE__ */ h("p", {
|
|
257
|
-
className: "text-sm text-
|
|
257
|
+
className: "text-sm text-text-secondary",
|
|
258
258
|
children: b("billing.addons.addonNotFoundMessage", "The addon you're looking for doesn't exist or has been removed.")
|
|
259
259
|
}),
|
|
260
260
|
/* @__PURE__ */ h("button", {
|
|
261
261
|
type: "button",
|
|
262
262
|
onClick: () => S("/addons"),
|
|
263
|
-
className: "px-4 py-2 text-sm font-medium bg-primary text-primary-
|
|
263
|
+
className: "px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors",
|
|
264
264
|
children: "Back to Addons"
|
|
265
265
|
})
|
|
266
266
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AddonBrowseDetailPage.js","names":[],"sources":["../../../../../src/billing/modules/addons/pages/AddonBrowseDetailPage.tsx"],"sourcesContent":["/**\n * Addons Module - Addon Browse Detail Page (User-facing)\n * View addon details and add to cart. No edit/toggle actions.\n */\n\nimport { useMemo, type FC } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ShoppingCart, Plus, Minus, Trash2 } from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useAddon } from '../hooks';\nimport { useAddonCartStore } from '../store/addonCartStore';\nimport { PageHeader, ServerError } from '../../../shared/components';\nimport {\n formatCurrency,\n formatPlanDuration,\n formatPlanDurationLabel,\n isServerError,\n} from '../../../shared/utils';\nimport type { SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n type: string;\n}\n\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n for (const feature of features) {\n if (!feature.quota) continue;\n const quotaId = feature.quota.id;\n const limits = feature.quota.limits as { value?: number; type?: string } | null;\n const limitValue = limits?.value ?? 0;\n const limitType = limits?.type ?? 'unknown';\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 type: limitType,\n });\n }\n }\n return Array.from(quotaMap.values());\n}\n\nexport const AddonBrowseDetailPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { addonId } = useParams<{ addonId: string }>();\n const navigateTo = useBillingNavigate();\n const { addon, isLoading, error, refetch } = useAddon(addonId);\n const { addToCart, removeFromCart, updateQuantity, isInCart, getCartItem } = useAddonCartStore();\n\n const combinedQuotas = useMemo(() => combineQuotas(addon?.features || []), [addon?.features]);\n const inCart = addon ? isInCart(addon.id) : false;\n const cartItem = addon ? getCartItem(addon.id) : undefined;\n const cartQuantity = cartItem?.quantity || 0;\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"h-24 bg-muted animate-pulse rounded\" />\n ))}\n </div>\n <div className=\"h-64 bg-muted animate-pulse rounded\" />\n </div>\n </div>\n );\n }\n\n if (error && isServerError(error)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title={tr('billing.addons.serverUnavailable', 'Server Unavailable')}\n message={tr('billing.addons.unableToLoadAddonDetails', 'Unable to load addon details.')}\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n if (!addon) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr('billing.addons.addonNotFound', 'Addon not found')}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n 'billing.addons.addonNotFoundMessage',\n \"The addon you're looking for doesn't exist or has been removed.\"\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons')}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Back to Addons\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={addon.name}\n description={`${formatPlanDurationLabel(addon.duration)} addon`}\n />\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Pricing Card */}\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.addons.pricing', 'Pricing')}\n </h2>\n </div>\n <div className=\"p-6\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-4xl font-bold text-foreground\">\n {formatCurrency(addon.price, addon.currency)}\n </span>\n <span className=\"text-lg text-muted-foreground\">\n / {formatPlanDuration(addon.duration)}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-2\">\n {tr('billing.addons.billed', 'Billed')}{' '}\n {addon.duration === 'monthly'\n ? tr('billing.addons.everyMonth', 'every month')\n : tr('billing.addons.annually', 'annually')}\n </p>\n </div>\n </div>\n\n {/* Quotas Card */}\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.addons.includedQuotas', 'Included Quotas')} ({combinedQuotas.length})\n </h2>\n </div>\n <div className=\"p-4\">\n {combinedQuotas.length === 0 ? (\n <p className=\"text-sm text-muted-foreground py-4 text-center\">\n {tr('billing.addons.noQuotas', 'No quotas associated with this addon.')}\n </p>\n ) : (\n <div className=\"space-y-3\">\n {combinedQuotas.map((quota) => (\n <div\n key={quota.quotaId}\n className=\"flex items-center justify-between p-3 border border-border rounded-lg bg-muted/20\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"size-8 rounded-full bg-primary/10 flex items-center justify-center\">\n <svg\n className=\"size-4 text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n </div>\n <div>\n <p className=\"font-medium text-foreground\">{quota.name}</p>\n <p className=\"text-xs text-muted-foreground capitalize\">\n Type: {quota.type}\n </p>\n </div>\n </div>\n <div className=\"text-right\">\n <span className=\"text-lg font-semibold text-status-success-text\">\n {quota.totalValue.toLocaleString()}\n </span>\n <p className=\"text-xs text-muted-foreground\">total</p>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Purchase Card */}\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.addons.purchase', 'Purchase')}\n </h2>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {tr('billing.addons.price', 'Price')}\n </span>\n <span className=\"text-sm font-medium text-foreground\">\n {formatCurrency(addon.price, addon.currency)} /{' '}\n {formatPlanDuration(addon.duration)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-muted-foreground\">\n {tr('billing.addons.billingLabel', 'Billing')}\n </span>\n <span className=\"text-sm font-medium text-foreground capitalize\">\n {addon.duration}\n </span>\n </div>\n\n <div className=\"pt-2 space-y-2\">\n {inCart ? (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-10 text-center font-medium\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border hover:bg-muted transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={() => removeFromCart(addon.id)}\n className=\"p-1.5 rounded text-destructive hover:bg-destructive/10 transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/checkout/addons')}\n className=\"w-full px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Proceed to Checkout\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => addToCart(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors flex items-center justify-center gap-2\"\n >\n <ShoppingCart className=\"size-4\" />\n Add to Cart\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons')}\n className=\"w-full px-4 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Back to Addons\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AddonBrowseDetailPage.js","names":[],"sources":["../../../../../src/billing/modules/addons/pages/AddonBrowseDetailPage.tsx"],"sourcesContent":["/**\n * Addons Module - Addon Browse Detail Page (User-facing)\n * View addon details and add to cart. No edit/toggle actions.\n */\n\nimport { useMemo, type FC } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { ShoppingCart, Plus, Minus, Trash2 } from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useAddon } from '../hooks';\nimport { useAddonCartStore } from '../store/addonCartStore';\nimport { PageHeader, ServerError } from '../../../shared/components';\nimport {\n formatCurrency,\n formatPlanDuration,\n formatPlanDurationLabel,\n isServerError,\n} from '../../../shared/utils';\nimport type { SubscriptionFeatures } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface CombinedQuota {\n quotaId: string;\n name: string;\n totalValue: number;\n type: string;\n}\n\nfunction combineQuotas(features: SubscriptionFeatures[]): CombinedQuota[] {\n const quotaMap = new Map<string, CombinedQuota>();\n for (const feature of features) {\n if (!feature.quota) continue;\n const quotaId = feature.quota.id;\n const limits = feature.quota.limits as { value?: number; type?: string } | null;\n const limitValue = limits?.value ?? 0;\n const limitType = limits?.type ?? 'unknown';\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 type: limitType,\n });\n }\n }\n return Array.from(quotaMap.values());\n}\n\nexport const AddonBrowseDetailPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { addonId } = useParams<{ addonId: string }>();\n const navigateTo = useBillingNavigate();\n const { addon, isLoading, error, refetch } = useAddon(addonId);\n const { addToCart, removeFromCart, updateQuantity, isInCart, getCartItem } = useAddonCartStore();\n\n const combinedQuotas = useMemo(() => combineQuotas(addon?.features || []), [addon?.features]);\n const inCart = addon ? isInCart(addon.id) : false;\n const cartItem = addon ? getCartItem(addon.id) : undefined;\n const cartQuantity = cartItem?.quantity || 0;\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-bg-sunken animate-pulse rounded\" />\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n <div className=\"lg:col-span-2 space-y-4\">\n {[1, 2, 3].map((i) => (\n <div key={i} className=\"h-24 bg-bg-sunken animate-pulse rounded\" />\n ))}\n </div>\n <div className=\"h-64 bg-bg-sunken animate-pulse rounded\" />\n </div>\n </div>\n );\n }\n\n if (error && isServerError(error)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title={tr('billing.addons.serverUnavailable', 'Server Unavailable')}\n message={tr('billing.addons.unableToLoadAddonDetails', 'Unable to load addon details.')}\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n if (!addon) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr('billing.addons.addonNotFound', 'Addon not found')}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n 'billing.addons.addonNotFoundMessage',\n \"The addon you're looking for doesn't exist or has been removed.\"\n )}\n </p>\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons')}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors\"\n >\n Back to Addons\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={addon.name}\n description={`${formatPlanDurationLabel(addon.duration)} addon`}\n />\n\n <div className=\"grid grid-cols-1 lg:grid-cols-3 gap-6\">\n {/* Main Content */}\n <div className=\"lg:col-span-2 space-y-6\">\n {/* Pricing Card */}\n <div className=\"border border-border-subtle rounded-lg bg-bg-surface overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.addons.pricing', 'Pricing')}\n </h2>\n </div>\n <div className=\"p-6\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-4xl font-bold text-text-primary\">\n {formatCurrency(addon.price, addon.currency)}\n </span>\n <span className=\"text-lg text-text-secondary\">\n / {formatPlanDuration(addon.duration)}\n </span>\n </div>\n <p className=\"text-sm text-text-secondary mt-2\">\n {tr('billing.addons.billed', 'Billed')}{' '}\n {addon.duration === 'monthly'\n ? tr('billing.addons.everyMonth', 'every month')\n : tr('billing.addons.annually', 'annually')}\n </p>\n </div>\n </div>\n\n {/* Quotas Card */}\n <div className=\"border border-border-subtle rounded-lg bg-bg-surface overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.addons.includedQuotas', 'Included Quotas')} ({combinedQuotas.length})\n </h2>\n </div>\n <div className=\"p-4\">\n {combinedQuotas.length === 0 ? (\n <p className=\"text-sm text-text-secondary py-4 text-center\">\n {tr('billing.addons.noQuotas', 'No quotas associated with this addon.')}\n </p>\n ) : (\n <div className=\"space-y-3\">\n {combinedQuotas.map((quota) => (\n <div\n key={quota.quotaId}\n className=\"flex items-center justify-between p-3 border border-border-subtle rounded-lg bg-bg-sunken/20\"\n >\n <div className=\"flex items-center gap-3\">\n <div className=\"size-8 rounded-full bg-action-primary-bg/10 flex items-center justify-center\">\n <svg\n className=\"size-4 text-primary\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n </div>\n <div>\n <p className=\"font-medium text-text-primary\">{quota.name}</p>\n <p className=\"text-xs text-text-secondary capitalize\">\n Type: {quota.type}\n </p>\n </div>\n </div>\n <div className=\"text-right\">\n <span className=\"text-lg font-semibold text-status-success-text\">\n {quota.totalValue.toLocaleString()}\n </span>\n <p className=\"text-xs text-text-secondary\">total</p>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Sidebar */}\n <div className=\"space-y-6\">\n {/* Purchase Card */}\n <div className=\"border border-border-subtle rounded-lg bg-bg-surface overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.addons.purchase', 'Purchase')}\n </h2>\n </div>\n <div className=\"p-4 space-y-4\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr('billing.addons.price', 'Price')}\n </span>\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(addon.price, addon.currency)} /{' '}\n {formatPlanDuration(addon.duration)}\n </span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-sm text-text-secondary\">\n {tr('billing.addons.billingLabel', 'Billing')}\n </span>\n <span className=\"text-sm font-medium text-text-primary capitalize\">\n {addon.duration}\n </span>\n </div>\n\n <div className=\"pt-2 space-y-2\">\n {inCart ? (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2\">\n <div className=\"flex items-center gap-1\">\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, cartQuantity - 1)}\n className=\"p-1.5 rounded border border-border-subtle hover:bg-bg-sunken transition-colors\"\n >\n <Minus className=\"size-4\" />\n </button>\n <span className=\"w-10 text-center font-medium\">{cartQuantity}</span>\n <button\n type=\"button\"\n onClick={() => updateQuantity(addon.id, cartQuantity + 1)}\n className=\"p-1.5 rounded border border-border-subtle hover:bg-bg-sunken transition-colors\"\n >\n <Plus className=\"size-4\" />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={() => removeFromCart(addon.id)}\n className=\"p-1.5 rounded text-status-error-text hover:bg-status-error-bg/10 transition-colors\"\n title=\"Remove from cart\"\n >\n <Trash2 className=\"size-4\" />\n </button>\n </div>\n <button\n type=\"button\"\n onClick={() => navigateTo('/checkout/addons')}\n className=\"w-full px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors\"\n >\n Proceed to Checkout\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={() => addToCart(addon)}\n className=\"w-full px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bg/90 transition-colors flex items-center justify-center gap-2\"\n >\n <ShoppingCart className=\"size-4\" />\n Add to Cart\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Back Button */}\n <button\n type=\"button\"\n onClick={() => navigateTo('/addons')}\n className=\"w-full px-4 py-2 text-sm font-medium border border-border-subtle text-text-primary rounded-md hover:bg-bg-sunken transition-colors\"\n >\n Back to Addons\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|