@burdenoff/microfe-billing 2026.913.1 → 2026.915.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.
Files changed (45) hide show
  1. package/dist/billing/BillingAdminRoutes.js +84 -71
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/modules/billing/hooks/useRefunds.js.map +1 -1
  4. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +90 -87
  5. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
  6. package/dist/billing/modules/billing/pages/RefundIssueLogsPage.js +97 -58
  7. package/dist/billing/modules/billing/pages/RefundIssueLogsPage.js.map +1 -1
  8. package/dist/billing/modules/checkout/components/OrderSummary.js +22 -19
  9. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  10. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
  11. package/dist/billing/modules/checkout/components/StoreShippingSection.js +191 -177
  12. package/dist/billing/modules/checkout/components/StoreShippingSection.js.map +1 -1
  13. package/dist/billing/modules/checkout/hooks/useCheckout.js +174 -157
  14. package/dist/billing/modules/checkout/hooks/useCheckout.js.map +1 -1
  15. package/dist/billing/modules/checkout/pages/CheckoutPage.js +191 -184
  16. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  17. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +293 -274
  18. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  19. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +140 -250
  20. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  21. package/dist/billing/modules/earnings/api.js +79 -42
  22. package/dist/billing/modules/earnings/api.js.map +1 -1
  23. package/dist/billing/modules/earnings/index.js +4 -3
  24. package/dist/billing/modules/earnings/pages/DeveloperRevenueAdminPage.js +103 -310
  25. package/dist/billing/modules/earnings/pages/DeveloperRevenueAdminPage.js.map +1 -1
  26. package/dist/billing/modules/earnings/pages/DeveloperRevenueOrgDetailPage.js +545 -0
  27. package/dist/billing/modules/earnings/pages/DeveloperRevenueOrgDetailPage.js.map +1 -0
  28. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +246 -196
  29. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  30. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js +44 -28
  31. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js.map +1 -1
  32. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +317 -270
  33. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  34. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +153 -150
  35. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  36. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +1 -1
  37. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  38. package/dist/billing/modules/usage/hooks/useUsage.js +74 -48
  39. package/dist/billing/modules/usage/hooks/useUsage.js.map +1 -1
  40. package/dist/generated/global-operations.js +220 -183
  41. package/dist/generated/global-operations.js.map +1 -1
  42. package/dist/generated/global-types.js.map +1 -1
  43. package/dist/node_modules/sonner/dist/index.js +163 -0
  44. package/dist/node_modules/sonner/dist/index.js.map +1 -0
  45. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"BillingAdminRoutes.js","names":[],"sources":["../../src/billing/BillingAdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, type ReactNode } from 'react';\nimport { Navigate, Route, Routes, useNavigate } from 'react-router';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useBillingEventEmitter, type BillingDomainEvent } from './hooks/useBillingEventEmitter';\nimport { useBillingPermissions } from './hooks/useBillingPermissions';\nimport { useBilling } from './providers/BillingProvider';\nimport { AccessDenied } from './shared/components';\n\n// Lazy loaded pages - Plans (full CRUD)\nconst PlansListPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlansListPage }))\n);\nconst PlanDetailPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanDetailPage }))\n);\nconst PlanEditPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanEditPage }))\n);\nconst PlanCreatePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanCreatePage }))\n);\nconst PlanAssignFreePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanAssignFreePage }))\n);\n\n// Lazy loaded pages - Addons (full CRUD)\nconst AddonsListPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonsListPage }))\n);\nconst AddonDetailPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonDetailPage }))\n);\nconst AddonEditPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonEditPage }))\n);\nconst AddonCreatePage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonCreatePage }))\n);\n\n// Lazy loaded pages - Quota Templates (full CRUD)\nconst QuotaTemplatesListPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplatesListPage }))\n);\nconst QuotaTemplateDetailPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateDetailPage }))\n);\nconst QuotaTemplateCreatePage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateCreatePage }))\n);\nconst QuotaTemplateEditPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateEditPage }))\n);\nconst QuotaAssignFreePage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaAssignFreePage }))\n);\n\n// Lazy loaded pages - Coupons\nconst CouponsListPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CouponsListPage }))\n);\nconst CreateCouponPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CreateCouponPage }))\n);\nconst EditCouponPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.EditCouponPage }))\n);\nconst CouponDetailPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CouponDetailPage }))\n);\n\n// Lazy loaded pages - Promotions\nconst PromotionsListPage = lazy(() =>\n import('./modules/promotions').then((m) => ({ default: m.PromotionsListPage }))\n);\nconst CreatePromotionPage = lazy(() =>\n import('./modules/promotions').then((m) => ({ default: m.CreatePromotionPage }))\n);\n\n// Lazy loaded pages - Discounts\nconst DiscountsListPage = lazy(() =>\n import('./modules/discounts').then((m) => ({ default: m.DiscountsListPage }))\n);\n\n// Lazy loaded pages - Refunds\nconst RefundsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.RefundsPage }))\n);\nconst RefundIssueLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.RefundIssueLogsPage }))\n);\n\n// Lazy loaded pages - Billing webhook logs\nconst BillingWebhookLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.BillingWebhookLogsPage }))\n);\n\n// Lazy loaded pages - Order callback logs\nconst OrderCallbackLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.OrderCallbackLogsPage }))\n);\n\n// Lazy loaded pages - Credits admin\nconst AdminCreditsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.AdminCreditsPage }))\n);\n\n// Lazy loaded pages - Analytics\nconst AnalyticsPage = lazy(() =>\n import('./modules/analytics').then((m) => ({ default: m.AnalyticsPage }))\n);\nconst DeveloperRevenueAdminPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.DeveloperRevenueAdminPage }))\n);\nconst PayoutAdminPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.PayoutAdminPage }))\n);\n\nfunction DefaultRedirect() {\n const { basePath } = useBilling();\n const routerNavigate = useNavigate();\n const base = basePath && basePath !== '/' ? basePath.replace(/\\/$/, '') : '';\n useEffect(() => {\n routerNavigate(`${base}/plans`, { replace: true });\n }, [base, routerNavigate]);\n return null;\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-action-primary-bg border-t-transparent\" />\n </div>\n );\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 BillingAdminRouteGateProps {\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-card border border-border-seam bg-bg-surface p-6 text-center shadow-[var(--shadow-elevation-1)]\">\n <h2 className=\"text-base 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{' '}\n <span className=\"font-mono text-xs text-text-secondary bg-bg-sunken/60 rounded px-1.5 py-0.5\">\n {featureFlag}\n </span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\nfunction BillingAdminRouteGate({\n title,\n featureFlag,\n permission,\n eventName,\n children,\n}: BillingAdminRouteGateProps) {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const hasPermission = Boolean(permissions[permission]);\n\n useEffect(() => {\n if (hasPermission) {\n emit(eventName, { source: 'BillingAdminRoutes' });\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 adminPage(props: BillingAdminRouteGateProps): ReactNode {\n return <BillingAdminRouteGate {...props} />;\n}\n\n/**\n * Admin-only billing routes.\n * Includes plans/addons/quota-templates CRUD, coupons, discounts, refunds, and analytics.\n */\nexport function BillingAdminRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"plans\" replace />} />\n\n {/* Plans - full CRUD */}\n <Route\n path=\"plans\"\n element={adminPage({\n title: 'Plans',\n featureFlag: 'billing.plans',\n permission: 'canViewPlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlansListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/new\"\n element={adminPage({\n title: 'Create plan',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/assign-free\"\n element={adminPage({\n title: 'Assign plan for free',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanAssignFreePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/:planId\"\n element={adminPage({\n title: 'Plan details',\n featureFlag: 'billing.plans',\n permission: 'canViewPlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/:planId/edit\"\n element={adminPage({\n title: 'Edit plan',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanEditPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Addons - full CRUD */}\n <Route\n path=\"addons\"\n element={adminPage({\n title: 'Addons',\n featureFlag: 'billing.addons',\n permission: 'canViewAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/new\"\n element={adminPage({\n title: 'Create addon',\n featureFlag: 'billing.addons.manage',\n permission: 'canManageAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/:addonId\"\n element={adminPage({\n title: 'Addon details',\n featureFlag: 'billing.addons',\n permission: 'canViewAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/:addonId/edit\"\n element={adminPage({\n title: 'Edit addon',\n featureFlag: 'billing.addons.manage',\n permission: 'canManageAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonEditPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Quota Templates - full CRUD */}\n <Route\n path=\"quotas\"\n element={adminPage({\n title: 'Quota templates',\n featureFlag: 'billing.quotas',\n permission: 'canViewQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplatesListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/new\"\n element={adminPage({\n title: 'Create quota template',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/:quotaId\"\n element={adminPage({\n title: 'Quota template details',\n featureFlag: 'billing.quotas',\n permission: 'canViewQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/:quotaId/edit\"\n element={adminPage({\n title: 'Edit quota template',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateEditPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/assign-free\"\n element={adminPage({\n title: 'Assign quota for free',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaAssignFreePage />\n </Suspense>\n ),\n })}\n />\n\n {/* Coupons */}\n <Route\n path=\"coupons\"\n element={adminPage({\n title: 'Coupons',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CouponsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/create\"\n element={adminPage({\n title: 'Create coupon',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CreateCouponPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/:id\"\n element={adminPage({\n title: 'Coupon details',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CouponDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/:id/edit\"\n element={adminPage({\n title: 'Edit coupon',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <EditCouponPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Promotions */}\n <Route\n path=\"promotions\"\n element={adminPage({\n title: 'Promotions',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PromotionsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"promotions/create\"\n element={adminPage({\n title: 'Create Promotion',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CreatePromotionPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Discounts */}\n <Route\n path=\"discounts\"\n element={adminPage({\n title: 'Discounts',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <DiscountsListPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Credit grants */}\n <Route\n path=\"credits\"\n element={adminPage({\n title: 'Credit grants',\n featureFlag: 'billing.credits.grants',\n permission: 'canGrantCredits',\n eventName: 'billing.credit.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AdminCreditsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Refunds */}\n <Route\n path=\"refunds\"\n element={adminPage({\n title: 'Refunds',\n featureFlag: 'billing.refunds',\n permission: 'canProcessRefund',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <RefundsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Refund issue log — refunds that completed at the gateway but left an\n unresolved accounting/reconciliation issue (BOFF-7192) */}\n <Route\n path=\"refunds/logs\"\n element={adminPage({\n title: 'Refund Issue Log',\n featureFlag: 'billing.refunds',\n permission: 'canProcessRefund',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <RefundIssueLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Billing webhook logs */}\n <Route\n path=\"webhook-logs\"\n element={adminPage({\n title: 'Billing webhook logs',\n featureFlag: 'billing.webhook-logs',\n permission: 'isBillingAdmin',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <BillingWebhookLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Order callback logs */}\n <Route\n path=\"order-callback-logs\"\n element={adminPage({\n title: 'Order callback logs',\n featureFlag: 'billing.order-callback-logs',\n permission: 'isBillingAdmin',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <OrderCallbackLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Analytics */}\n <Route\n path=\"analytics\"\n element={adminPage({\n title: 'Billing analytics',\n featureFlag: 'billing.analytics',\n permission: 'canViewAnalytics',\n eventName: 'billing.usage.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AnalyticsPage />\n </Suspense>\n ),\n })}\n />\n\n <Route\n path=\"developer-revenue\"\n element={adminPage({\n title: 'Developer revenue',\n featureFlag: 'billing.payouts.admin',\n permission: 'isBillingAdmin',\n eventName: 'billing.payout.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <DeveloperRevenueAdminPage />\n </Suspense>\n ),\n })}\n />\n\n <Route\n path=\"payouts\"\n element={adminPage({\n title: 'Payout administration',\n featureFlag: 'billing.payouts.admin',\n permission: 'isBillingAdmin',\n eventName: 'billing.payout.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PayoutAdminPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Catch-all — uses absolute path to avoid relative-navigation loop */}\n <Route path=\"*\" element={<DefaultRedirect />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"BillingAdminRoutes.js","names":[],"sources":["../../src/billing/BillingAdminRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, useEffect, type ReactNode } from 'react';\nimport { Navigate, Route, Routes, useNavigate } from 'react-router';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useBillingEventEmitter, type BillingDomainEvent } from './hooks/useBillingEventEmitter';\nimport { useBillingPermissions } from './hooks/useBillingPermissions';\nimport { useBilling } from './providers/BillingProvider';\nimport { AccessDenied } from './shared/components';\n\n// Lazy loaded pages - Plans (full CRUD)\nconst PlansListPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlansListPage }))\n);\nconst PlanDetailPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanDetailPage }))\n);\nconst PlanEditPage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanEditPage }))\n);\nconst PlanCreatePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanCreatePage }))\n);\nconst PlanAssignFreePage = lazy(() =>\n import('./modules/plans').then((m) => ({ default: m.PlanAssignFreePage }))\n);\n\n// Lazy loaded pages - Addons (full CRUD)\nconst AddonsListPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonsListPage }))\n);\nconst AddonDetailPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonDetailPage }))\n);\nconst AddonEditPage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonEditPage }))\n);\nconst AddonCreatePage = lazy(() =>\n import('./modules/addons').then((m) => ({ default: m.AddonCreatePage }))\n);\n\n// Lazy loaded pages - Quota Templates (full CRUD)\nconst QuotaTemplatesListPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplatesListPage }))\n);\nconst QuotaTemplateDetailPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateDetailPage }))\n);\nconst QuotaTemplateCreatePage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateCreatePage }))\n);\nconst QuotaTemplateEditPage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaTemplateEditPage }))\n);\nconst QuotaAssignFreePage = lazy(() =>\n import('./modules/quota').then((m) => ({ default: m.QuotaAssignFreePage }))\n);\n\n// Lazy loaded pages - Coupons\nconst CouponsListPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CouponsListPage }))\n);\nconst CreateCouponPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CreateCouponPage }))\n);\nconst EditCouponPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.EditCouponPage }))\n);\nconst CouponDetailPage = lazy(() =>\n import('./modules/coupons').then((m) => ({ default: m.CouponDetailPage }))\n);\n\n// Lazy loaded pages - Promotions\nconst PromotionsListPage = lazy(() =>\n import('./modules/promotions').then((m) => ({ default: m.PromotionsListPage }))\n);\nconst CreatePromotionPage = lazy(() =>\n import('./modules/promotions').then((m) => ({ default: m.CreatePromotionPage }))\n);\n\n// Lazy loaded pages - Discounts\nconst DiscountsListPage = lazy(() =>\n import('./modules/discounts').then((m) => ({ default: m.DiscountsListPage }))\n);\n\n// Lazy loaded pages - Refunds\nconst RefundsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.RefundsPage }))\n);\nconst RefundIssueLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.RefundIssueLogsPage }))\n);\n\n// Lazy loaded pages - Billing webhook logs\nconst BillingWebhookLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.BillingWebhookLogsPage }))\n);\n\n// Lazy loaded pages - Order callback logs\nconst OrderCallbackLogsPage = lazy(() =>\n import('./modules/billing').then((m) => ({ default: m.OrderCallbackLogsPage }))\n);\n\n// Lazy loaded pages - Credits admin\nconst AdminCreditsPage = lazy(() =>\n import('./modules/credits').then((m) => ({ default: m.AdminCreditsPage }))\n);\n\n// Lazy loaded pages - Analytics\nconst AnalyticsPage = lazy(() =>\n import('./modules/analytics').then((m) => ({ default: m.AnalyticsPage }))\n);\nconst DeveloperRevenueAdminPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.DeveloperRevenueAdminPage }))\n);\nconst DeveloperRevenueOrgDetailPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.DeveloperRevenueOrgDetailPage }))\n);\nconst PayoutAdminPage = lazy(() =>\n import('./modules/earnings').then((m) => ({ default: m.PayoutAdminPage }))\n);\n\nfunction DefaultRedirect() {\n const { basePath } = useBilling();\n const routerNavigate = useNavigate();\n const base = basePath && basePath !== '/' ? basePath.replace(/\\/$/, '') : '';\n useEffect(() => {\n routerNavigate(`${base}/plans`, { replace: true });\n }, [base, routerNavigate]);\n return null;\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-action-primary-bg border-t-transparent\" />\n </div>\n );\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 BillingAdminRouteGateProps {\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-card border border-border-seam bg-bg-surface p-6 text-center shadow-[var(--shadow-elevation-1)]\">\n <h2 className=\"text-base 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{' '}\n <span className=\"font-mono text-xs text-text-secondary bg-bg-sunken/60 rounded px-1.5 py-0.5\">\n {featureFlag}\n </span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\nfunction BillingAdminRouteGate({\n title,\n featureFlag,\n permission,\n eventName,\n children,\n}: BillingAdminRouteGateProps) {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const hasPermission = Boolean(permissions[permission]);\n\n useEffect(() => {\n if (hasPermission) {\n emit(eventName, { source: 'BillingAdminRoutes' });\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 adminPage(props: BillingAdminRouteGateProps): ReactNode {\n return <BillingAdminRouteGate {...props} />;\n}\n\n/**\n * Admin-only billing routes.\n * Includes plans/addons/quota-templates CRUD, coupons, discounts, refunds, and analytics.\n */\nexport function BillingAdminRoutes() {\n return (\n <Routes>\n <Route index element={<Navigate to=\"plans\" replace />} />\n\n {/* Plans - full CRUD */}\n <Route\n path=\"plans\"\n element={adminPage({\n title: 'Plans',\n featureFlag: 'billing.plans',\n permission: 'canViewPlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlansListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/new\"\n element={adminPage({\n title: 'Create plan',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/assign-free\"\n element={adminPage({\n title: 'Assign plan for free',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanAssignFreePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/:planId\"\n element={adminPage({\n title: 'Plan details',\n featureFlag: 'billing.plans',\n permission: 'canViewPlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"plans/:planId/edit\"\n element={adminPage({\n title: 'Edit plan',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PlanEditPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Addons - full CRUD */}\n <Route\n path=\"addons\"\n element={adminPage({\n title: 'Addons',\n featureFlag: 'billing.addons',\n permission: 'canViewAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/new\"\n element={adminPage({\n title: 'Create addon',\n featureFlag: 'billing.addons.manage',\n permission: 'canManageAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/:addonId\"\n element={adminPage({\n title: 'Addon details',\n featureFlag: 'billing.addons',\n permission: 'canViewAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"addons/:addonId/edit\"\n element={adminPage({\n title: 'Edit addon',\n featureFlag: 'billing.addons.manage',\n permission: 'canManageAddons',\n eventName: 'billing.addon.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AddonEditPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Quota Templates - full CRUD */}\n <Route\n path=\"quotas\"\n element={adminPage({\n title: 'Quota templates',\n featureFlag: 'billing.quotas',\n permission: 'canViewQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplatesListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/new\"\n element={adminPage({\n title: 'Create quota template',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateCreatePage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/:quotaId\"\n element={adminPage({\n title: 'Quota template details',\n featureFlag: 'billing.quotas',\n permission: 'canViewQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/:quotaId/edit\"\n element={adminPage({\n title: 'Edit quota template',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaTemplateEditPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"quotas/assign-free\"\n element={adminPage({\n title: 'Assign quota for free',\n featureFlag: 'billing.quotas.manage',\n permission: 'canManageQuotas',\n eventName: 'billing.quota.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <QuotaAssignFreePage />\n </Suspense>\n ),\n })}\n />\n\n {/* Coupons */}\n <Route\n path=\"coupons\"\n element={adminPage({\n title: 'Coupons',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CouponsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/create\"\n element={adminPage({\n title: 'Create coupon',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CreateCouponPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/:id\"\n element={adminPage({\n title: 'Coupon details',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CouponDetailPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"coupons/:id/edit\"\n element={adminPage({\n title: 'Edit coupon',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <EditCouponPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Promotions */}\n <Route\n path=\"promotions\"\n element={adminPage({\n title: 'Promotions',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PromotionsListPage />\n </Suspense>\n ),\n })}\n />\n <Route\n path=\"promotions/create\"\n element={adminPage({\n title: 'Create Promotion',\n featureFlag: 'billing.plans.manage',\n permission: 'canManagePlans',\n eventName: 'billing.plan.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <CreatePromotionPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Discounts */}\n <Route\n path=\"discounts\"\n element={adminPage({\n title: 'Discounts',\n featureFlag: 'billing.discounts',\n permission: 'canManageDiscounts',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <DiscountsListPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Credit grants */}\n <Route\n path=\"credits\"\n element={adminPage({\n title: 'Credit grants',\n featureFlag: 'billing.credits.grants',\n permission: 'canGrantCredits',\n eventName: 'billing.credit.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AdminCreditsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Refunds */}\n <Route\n path=\"refunds\"\n element={adminPage({\n title: 'Refunds',\n featureFlag: 'billing.refunds',\n permission: 'canProcessRefund',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <RefundsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Refund issue log — refunds that completed at the gateway but left an\n unresolved accounting/reconciliation issue (BOFF-7192) */}\n <Route\n path=\"refunds/logs\"\n element={adminPage({\n title: 'Refund Issue Log',\n featureFlag: 'billing.refunds',\n permission: 'canProcessRefund',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <RefundIssueLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Billing webhook logs */}\n <Route\n path=\"webhook-logs\"\n element={adminPage({\n title: 'Billing webhook logs',\n featureFlag: 'billing.webhook-logs',\n permission: 'isBillingAdmin',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <BillingWebhookLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Order callback logs */}\n <Route\n path=\"order-callback-logs\"\n element={adminPage({\n title: 'Order callback logs',\n featureFlag: 'billing.order-callback-logs',\n permission: 'isBillingAdmin',\n eventName: 'billing.transaction.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <OrderCallbackLogsPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Analytics */}\n <Route\n path=\"analytics\"\n element={adminPage({\n title: 'Billing analytics',\n featureFlag: 'billing.analytics',\n permission: 'canViewAnalytics',\n eventName: 'billing.usage.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <AnalyticsPage />\n </Suspense>\n ),\n })}\n />\n\n <Route\n path=\"developer-revenue\"\n element={adminPage({\n title: 'Developer revenue',\n featureFlag: 'billing.payouts.admin',\n permission: 'isBillingAdmin',\n eventName: 'billing.payout.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <DeveloperRevenueAdminPage />\n </Suspense>\n ),\n })}\n />\n\n <Route\n path=\"developer-revenue/:organizationId\"\n element={adminPage({\n title: 'Developer revenue detail',\n featureFlag: 'billing.payouts.admin',\n permission: 'isBillingAdmin',\n eventName: 'billing.payout.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <DeveloperRevenueOrgDetailPage />\n </Suspense>\n ),\n })}\n />\n\n <Route\n path=\"payouts\"\n element={adminPage({\n title: 'Payout administration',\n featureFlag: 'billing.payouts.admin',\n permission: 'isBillingAdmin',\n eventName: 'billing.payout.viewed',\n children: (\n <Suspense fallback={<PageLoader />}>\n <PayoutAdminPage />\n </Suspense>\n ),\n })}\n />\n\n {/* Catch-all — uses absolute path to avoid relative-navigation loop */}\n <Route path=\"*\" element={<DefaultRedirect />} />\n </Routes>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useRefunds.js","names":[],"sources":["../../../../../src/billing/modules/billing/hooks/useRefunds.ts"],"sourcesContent":["/**\n * Billing Module - useRefunds Hook\n * Provides access to refund records, statistics, and mutations\n */\n\nimport { useApolloClient } from '@apollo/client/react';\nimport { useCallback, useState, useMemo, useEffect } from 'react';\nimport {\n useGetRefundRecordsQuery,\n useGetPendingRefundsQuery,\n useGetRefundRecordQuery,\n useGetRefundStatsQuery,\n useGetUnprocessedFailedWebhooksQuery,\n useGetBillingWebhookLogsQuery,\n useCreateRefundRecordMutation,\n useProcessRefundMutation,\n useSkipRefundMutation,\n useRetryRefundMutation,\n useCreateRefundRecordsFromFailedWebhooksMutation,\n useCreateRefundRecordFromWebhookMutation,\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n GetBillingWebhookLogsDocument,\n} from '../../../../generated/global-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RefundRecordStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'SKIPPED';\nexport type RefundSource =\n 'MANUAL' | 'WEBHOOK_RECOVERY' | 'SUBSCRIPTION_CANCEL' | 'DUPLICATE_PAYMENT';\n\nexport interface RefundRecord {\n id: string;\n orgId: string;\n billingAccountId: string | null;\n source: RefundSource;\n status: RefundRecordStatus;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId: string | null;\n amount: number;\n currency: string;\n purchaseType: string | null;\n purchaseDetail: string | null;\n reason: string | null;\n notes: string | null;\n webhookLogId: string | null;\n transactionId: string | null;\n processedBy: string | null;\n processedAt: string | null;\n gatewayRefundId: string | null;\n errorMessage: string | null;\n retryCount: number;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface RefundStats {\n pending: number;\n processing: number;\n completed: number;\n failed: number;\n skipped: number;\n totalPendingAmount: number;\n totalCompletedAmount: number;\n}\n\nexport interface WebhookLog {\n id: string;\n event: string;\n provider: string;\n payload: Record<string, unknown>;\n processed: boolean;\n error: string | null;\n createdAt: string;\n}\n\nexport interface RefundRecordFilters {\n status?: RefundRecordStatus;\n source?: RefundSource;\n provider?: string;\n billingAccountId?: string;\n fromDate?: string;\n toDate?: string;\n /** true → only refunds carrying a non-null errorMessage (an unresolved\n * accounting/reconciliation issue). Powers the admin refund issue log. */\n hasError?: boolean;\n}\n\nexport interface CreateRefundRecordInput {\n billingAccountId?: string;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId?: string;\n amount: number;\n currency: string;\n purchaseType?: string;\n purchaseDetail?: string;\n reason?: string;\n notes?: string;\n transactionId?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ProcessRefundResult {\n success: boolean;\n refundRecord: RefundRecord | null;\n gatewayRefundId: string | null;\n error: string | null;\n}\n\ninterface PaginationInfo {\n totalCount: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n hasPrevious: boolean;\n}\n\n// ============================================================================\n// Hook Results\n// ============================================================================\n\ninterface UseRefundRecordsOptions {\n pageSize?: number;\n filters?: RefundRecordFilters;\n}\n\ninterface UseRefundRecordsResult {\n records: RefundRecord[];\n pagination: PaginationInfo;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n goToNextPage: () => void;\n goToPreviousPage: () => void;\n goToPage: (page: number) => void;\n setFilters: (filters: RefundRecordFilters) => void;\n}\n\ninterface UseRefundStatsResult {\n stats: RefundStats | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseRefundRecordResult {\n record: RefundRecord | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseUnprocessedWebhooksResult {\n webhooks: WebhookLog[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\nexport interface BillingWebhookLogFilters {\n processed?: boolean;\n provider?: string;\n hasError?: boolean;\n}\n\ninterface UseBillingWebhookLogsResult {\n logs: WebhookLog[];\n totalCount: number;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseRefundMutationsResult {\n createRefundRecord: (input: CreateRefundRecordInput) => Promise<RefundRecord>;\n processRefund: (id: string, notes?: string) => Promise<ProcessRefundResult>;\n skipRefund: (id: string, reason: string) => Promise<RefundRecord>;\n retryRefund: (id: string) => Promise<ProcessRefundResult>;\n createRefundRecordsFromFailedWebhooks: () => Promise<RefundRecord[]>;\n createRefundRecordFromWebhook: (webhookLogId: string) => Promise<RefundRecord | null>;\n isCreating: boolean;\n isProcessing: boolean;\n isSkipping: boolean;\n isRetrying: boolean;\n isCreatingFromWebhooks: boolean;\n isCreatingFromWebhook: boolean;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nconst DEFAULT_PAGE_SIZE = 20;\n\n/**\n * Hook for fetching paginated refund records with filters\n */\nexport function useRefundRecords(options: UseRefundRecordsOptions = {}): UseRefundRecordsResult {\n const pageSize = options.pageSize || DEFAULT_PAGE_SIZE;\n const [currentPage, setCurrentPage] = useState(0);\n const [filters, setFilters] = useState<RefundRecordFilters>(options.filters || {});\n\n // Update filters when options change (e.g., when tab changes)\n useEffect(() => {\n setFilters(options.filters || {});\n setCurrentPage(0); // Reset to first page when filters change externally\n }, [options.filters]);\n\n const { data, loading, error, refetch } = useGetRefundRecordsQuery({\n variables: {\n ...filters,\n page: currentPage,\n pageSize,\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getRefundRecords;\n\n const goToNextPage = useCallback(() => {\n if (result?.hasMore) {\n setCurrentPage((prev) => prev + 1);\n }\n }, [result?.hasMore]);\n\n const goToPreviousPage = useCallback(() => {\n if (currentPage > 0) {\n setCurrentPage((prev) => prev - 1);\n }\n }, [currentPage]);\n\n const goToPage = useCallback(\n (page: number) => {\n const totalPages = result ? Math.ceil(result.totalCount / pageSize) : 0;\n if (page >= 0 && page < totalPages) {\n setCurrentPage(page);\n }\n },\n [result, pageSize]\n );\n\n const handleSetFilters = useCallback((newFilters: RefundRecordFilters) => {\n setFilters(newFilters);\n setCurrentPage(0); // Reset to first page when filters change\n }, []);\n\n return {\n records: result?.records || [],\n pagination: {\n totalCount: result?.totalCount || 0,\n hasMore: result?.hasMore || false,\n page: currentPage,\n pageSize,\n hasPrevious: currentPage > 0,\n },\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n setFilters: handleSetFilters,\n };\n}\n\n/**\n * Hook for fetching pending refund records (shortcut)\n */\nexport function usePendingRefunds(pageSize = DEFAULT_PAGE_SIZE): UseRefundRecordsResult {\n const [currentPage, setCurrentPage] = useState(0);\n\n const { data, loading, error, refetch } = useGetPendingRefundsQuery({\n variables: { page: currentPage, pageSize },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getPendingRefunds;\n\n const goToNextPage = useCallback(() => {\n if (result?.hasMore) {\n setCurrentPage((prev) => prev + 1);\n }\n }, [result?.hasMore]);\n\n const goToPreviousPage = useCallback(() => {\n if (currentPage > 0) {\n setCurrentPage((prev) => prev - 1);\n }\n }, [currentPage]);\n\n const goToPage = useCallback(\n (page: number) => {\n const totalPages = result ? Math.ceil(result.totalCount / pageSize) : 0;\n if (page >= 0 && page < totalPages) {\n setCurrentPage(page);\n }\n },\n [result, pageSize]\n );\n\n return {\n records: result?.records || [],\n pagination: {\n totalCount: result?.totalCount || 0,\n hasMore: result?.hasMore || false,\n page: currentPage,\n pageSize,\n hasPrevious: currentPage > 0,\n },\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n setFilters: () => {}, // No-op for pending refunds\n };\n}\n\n/**\n * Hook for fetching refund statistics\n */\nexport function useRefundStats(): UseRefundStatsResult {\n const { data, loading, error, refetch } = useGetRefundStatsQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n stats: data?.getRefundStats || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching a single refund record by ID\n */\nexport function useRefundRecord(id: string | undefined): UseRefundRecordResult {\n const { data, loading, error, refetch } = useGetRefundRecordQuery({\n variables: { id: id! },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n record: data?.getRefundRecord || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching unprocessed failed webhooks\n */\nexport function useUnprocessedFailedWebhooks(): UseUnprocessedWebhooksResult {\n const { data, loading, error, refetch } = useGetUnprocessedFailedWebhooksQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n webhooks: data?.getUnprocessedFailedWebhooks || [],\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for the admin billing-webhook-log viewer — paginated, filterable view\n * over ALL webhook log rows (unlike useUnprocessedFailedWebhooks, which only\n * scans the narrow refund-candidate subset).\n */\nexport function useBillingWebhookLogs(\n filters: BillingWebhookLogFilters,\n page: number,\n pageSize: number\n): UseBillingWebhookLogsResult {\n const { data, loading, error, refetch } = useGetBillingWebhookLogsQuery({\n variables: {\n limit: pageSize,\n offset: page * pageSize,\n processed: filters.processed,\n provider: filters.provider,\n hasError: filters.hasError,\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n logs: data?.getBillingWebhookLogs.logs || [],\n totalCount: data?.getBillingWebhookLogs.totalCount || 0,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for refund mutations\n */\nexport function useRefundMutations(): UseRefundMutationsResult {\n const client = useApolloClient();\n\n const [createRefundRecordMutation, { loading: isCreating }] = useCreateRefundRecordMutation();\n const [processRefundMutation, { loading: isProcessing }] = useProcessRefundMutation();\n const [skipRefundMutation, { loading: isSkipping }] = useSkipRefundMutation();\n const [retryRefundMutation, { loading: isRetrying }] = useRetryRefundMutation();\n const [createFromWebhooksMutation, { loading: isCreatingFromWebhooks }] =\n useCreateRefundRecordsFromFailedWebhooksMutation();\n const [createFromWebhookMutation, { loading: isCreatingFromWebhook }] =\n useCreateRefundRecordFromWebhookMutation();\n\n const refetchQueries = useCallback(async () => {\n await client.refetchQueries({\n include: [GetRefundRecordsDocument, GetPendingRefundsDocument, GetRefundStatsDocument],\n });\n }, [client]);\n\n const createRefundRecord = useCallback(\n async (input: CreateRefundRecordInput): Promise<RefundRecord> => {\n const { data } = await createRefundRecordMutation({\n variables: input,\n });\n await refetchQueries();\n return data.createRefundRecord;\n },\n [createRefundRecordMutation, refetchQueries]\n );\n\n const processRefund = useCallback(\n async (id: string, notes?: string): Promise<ProcessRefundResult> => {\n const { data } = await processRefundMutation({\n variables: { id, notes },\n });\n await refetchQueries();\n return data.processRefund;\n },\n [processRefundMutation, refetchQueries]\n );\n\n const skipRefund = useCallback(\n async (id: string, reason: string): Promise<RefundRecord> => {\n const { data } = await skipRefundMutation({\n variables: { id, reason },\n });\n await refetchQueries();\n return data.skipRefund;\n },\n [skipRefundMutation, refetchQueries]\n );\n\n const retryRefund = useCallback(\n async (id: string): Promise<ProcessRefundResult> => {\n const { data } = await retryRefundMutation({\n variables: { id },\n });\n await refetchQueries();\n return data.retryRefund;\n },\n [retryRefundMutation, refetchQueries]\n );\n\n const createRefundRecordsFromFailedWebhooks = useCallback(async (): Promise<RefundRecord[]> => {\n const { data } = await createFromWebhooksMutation();\n await client.refetchQueries({\n include: [\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n GetBillingWebhookLogsDocument,\n ],\n });\n return data!.createRefundRecordsFromFailedWebhooks;\n }, [createFromWebhooksMutation, client]);\n\n const createRefundRecordFromWebhook = useCallback(\n async (webhookLogId: string): Promise<RefundRecord | null> => {\n const { data } = await createFromWebhookMutation({\n variables: { webhookLogId },\n });\n await client.refetchQueries({\n include: [\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n ],\n });\n return data!.createRefundRecordFromWebhook;\n },\n [createFromWebhookMutation, client]\n );\n\n return {\n createRefundRecord,\n processRefund,\n skipRefund,\n retryRefund,\n createRefundRecordsFromFailedWebhooks,\n createRefundRecordFromWebhook,\n isCreating,\n isProcessing,\n isSkipping,\n isRetrying,\n isCreatingFromWebhooks,\n isCreatingFromWebhook,\n };\n}\n\n/**\n * Combined hook for refund page with all data and mutations\n */\nexport function useRefunds(options: UseRefundRecordsOptions = {}) {\n const recordsHook = useRefundRecords(options);\n const statsHook = useRefundStats();\n const mutationsHook = useRefundMutations();\n const webhooksHook = useUnprocessedFailedWebhooks();\n\n const isLoading = useMemo(\n () => recordsHook.isLoading || statsHook.isLoading,\n [recordsHook.isLoading, statsHook.isLoading]\n );\n\n const refetchAll = useCallback(async () => {\n await Promise.all([recordsHook.refetch(), statsHook.refetch(), webhooksHook.refetch()]);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Intentional: accessing stable refetch methods from hooks\n }, [recordsHook.refetch, statsHook.refetch, webhooksHook.refetch]);\n\n return {\n // Records\n records: recordsHook.records,\n pagination: recordsHook.pagination,\n goToNextPage: recordsHook.goToNextPage,\n goToPreviousPage: recordsHook.goToPreviousPage,\n goToPage: recordsHook.goToPage,\n setFilters: recordsHook.setFilters,\n\n // Stats\n stats: statsHook.stats,\n\n // Failed webhooks\n unprocessedWebhooks: webhooksHook.webhooks,\n webhooksLoading: webhooksHook.isLoading,\n\n // Loading states\n isLoading,\n recordsError: recordsHook.error,\n statsError: statsHook.error,\n\n // Mutations\n ...mutationsHook,\n\n // Refetch\n refetch: refetchAll,\n refetchRecords: recordsHook.refetch,\n refetchStats: statsHook.refetch,\n refetchWebhooks: webhooksHook.refetch,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRefunds.js","names":[],"sources":["../../../../../src/billing/modules/billing/hooks/useRefunds.ts"],"sourcesContent":["/**\n * Billing Module - useRefunds Hook\n * Provides access to refund records, statistics, and mutations\n */\n\nimport { useApolloClient } from '@apollo/client/react';\nimport { useCallback, useState, useMemo, useEffect } from 'react';\nimport {\n useGetRefundRecordsQuery,\n useGetPendingRefundsQuery,\n useGetRefundRecordQuery,\n useGetRefundStatsQuery,\n useGetUnprocessedFailedWebhooksQuery,\n useGetBillingWebhookLogsQuery,\n useCreateRefundRecordMutation,\n useProcessRefundMutation,\n useSkipRefundMutation,\n useRetryRefundMutation,\n useCreateRefundRecordsFromFailedWebhooksMutation,\n useCreateRefundRecordFromWebhookMutation,\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n GetBillingWebhookLogsDocument,\n} from '../../../../generated/global-operations';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RefundRecordStatus = 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'SKIPPED';\nexport type RefundSource =\n 'MANUAL' | 'WEBHOOK_RECOVERY' | 'SUBSCRIPTION_CANCEL' | 'DUPLICATE_PAYMENT';\n\nexport interface RefundRecord {\n id: string;\n orgId: string;\n billingAccountId: string | null;\n source: RefundSource;\n status: RefundRecordStatus;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId: string | null;\n amount: number;\n currency: string;\n purchaseType: string | null;\n purchaseDetail: string | null;\n reason: string | null;\n notes: string | null;\n webhookLogId: string | null;\n transactionId: string | null;\n processedBy: string | null;\n processedAt: string | null;\n gatewayRefundId: string | null;\n errorMessage: string | null;\n retryCount: number;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n updatedAt: string;\n}\n\nexport interface RefundStats {\n pending: number;\n processing: number;\n completed: number;\n failed: number;\n skipped: number;\n totalPendingAmount: number;\n totalCompletedAmount: number;\n}\n\nexport interface WebhookLog {\n id: string;\n event: string;\n provider: string;\n payload: Record<string, unknown>;\n processed: boolean;\n error: string | null;\n createdAt: string;\n}\n\nexport interface RefundRecordFilters {\n status?: RefundRecordStatus;\n source?: RefundSource;\n provider?: string;\n billingAccountId?: string;\n fromDate?: string;\n toDate?: string;\n /** true → only refunds carrying a non-null errorMessage (an unresolved\n * accounting/reconciliation issue). Powers the admin refund issue log. */\n hasError?: boolean;\n /** Free-text, matched against the refund id, the originating transaction\n * id, the gateway payment id, and the gateway refund id — lets an admin\n * find the refund/issue that belongs to a specific transaction. */\n search?: string;\n}\n\nexport interface CreateRefundRecordInput {\n billingAccountId?: string;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId?: string;\n amount: number;\n currency: string;\n purchaseType?: string;\n purchaseDetail?: string;\n reason?: string;\n notes?: string;\n transactionId?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface ProcessRefundResult {\n success: boolean;\n refundRecord: RefundRecord | null;\n gatewayRefundId: string | null;\n error: string | null;\n}\n\ninterface PaginationInfo {\n totalCount: number;\n hasMore: boolean;\n page: number;\n pageSize: number;\n hasPrevious: boolean;\n}\n\n// ============================================================================\n// Hook Results\n// ============================================================================\n\ninterface UseRefundRecordsOptions {\n pageSize?: number;\n filters?: RefundRecordFilters;\n}\n\ninterface UseRefundRecordsResult {\n records: RefundRecord[];\n pagination: PaginationInfo;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n goToNextPage: () => void;\n goToPreviousPage: () => void;\n goToPage: (page: number) => void;\n setFilters: (filters: RefundRecordFilters) => void;\n}\n\ninterface UseRefundStatsResult {\n stats: RefundStats | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseRefundRecordResult {\n record: RefundRecord | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseUnprocessedWebhooksResult {\n webhooks: WebhookLog[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\nexport interface BillingWebhookLogFilters {\n processed?: boolean;\n provider?: string;\n hasError?: boolean;\n}\n\ninterface UseBillingWebhookLogsResult {\n logs: WebhookLog[];\n totalCount: number;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseRefundMutationsResult {\n createRefundRecord: (input: CreateRefundRecordInput) => Promise<RefundRecord>;\n processRefund: (id: string, notes?: string) => Promise<ProcessRefundResult>;\n skipRefund: (id: string, reason: string) => Promise<RefundRecord>;\n retryRefund: (id: string) => Promise<ProcessRefundResult>;\n createRefundRecordsFromFailedWebhooks: () => Promise<RefundRecord[]>;\n createRefundRecordFromWebhook: (webhookLogId: string) => Promise<RefundRecord | null>;\n isCreating: boolean;\n isProcessing: boolean;\n isSkipping: boolean;\n isRetrying: boolean;\n isCreatingFromWebhooks: boolean;\n isCreatingFromWebhook: boolean;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\nconst DEFAULT_PAGE_SIZE = 20;\n\n/**\n * Hook for fetching paginated refund records with filters\n */\nexport function useRefundRecords(options: UseRefundRecordsOptions = {}): UseRefundRecordsResult {\n const pageSize = options.pageSize || DEFAULT_PAGE_SIZE;\n const [currentPage, setCurrentPage] = useState(0);\n const [filters, setFilters] = useState<RefundRecordFilters>(options.filters || {});\n\n // Update filters when options change (e.g., when tab changes)\n useEffect(() => {\n setFilters(options.filters || {});\n setCurrentPage(0); // Reset to first page when filters change externally\n }, [options.filters]);\n\n const { data, loading, error, refetch } = useGetRefundRecordsQuery({\n variables: {\n ...filters,\n page: currentPage,\n pageSize,\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getRefundRecords;\n\n const goToNextPage = useCallback(() => {\n if (result?.hasMore) {\n setCurrentPage((prev) => prev + 1);\n }\n }, [result?.hasMore]);\n\n const goToPreviousPage = useCallback(() => {\n if (currentPage > 0) {\n setCurrentPage((prev) => prev - 1);\n }\n }, [currentPage]);\n\n const goToPage = useCallback(\n (page: number) => {\n const totalPages = result ? Math.ceil(result.totalCount / pageSize) : 0;\n if (page >= 0 && page < totalPages) {\n setCurrentPage(page);\n }\n },\n [result, pageSize]\n );\n\n const handleSetFilters = useCallback((newFilters: RefundRecordFilters) => {\n setFilters(newFilters);\n setCurrentPage(0); // Reset to first page when filters change\n }, []);\n\n return {\n records: result?.records || [],\n pagination: {\n totalCount: result?.totalCount || 0,\n hasMore: result?.hasMore || false,\n page: currentPage,\n pageSize,\n hasPrevious: currentPage > 0,\n },\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n setFilters: handleSetFilters,\n };\n}\n\n/**\n * Hook for fetching pending refund records (shortcut)\n */\nexport function usePendingRefunds(pageSize = DEFAULT_PAGE_SIZE): UseRefundRecordsResult {\n const [currentPage, setCurrentPage] = useState(0);\n\n const { data, loading, error, refetch } = useGetPendingRefundsQuery({\n variables: { page: currentPage, pageSize },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getPendingRefunds;\n\n const goToNextPage = useCallback(() => {\n if (result?.hasMore) {\n setCurrentPage((prev) => prev + 1);\n }\n }, [result?.hasMore]);\n\n const goToPreviousPage = useCallback(() => {\n if (currentPage > 0) {\n setCurrentPage((prev) => prev - 1);\n }\n }, [currentPage]);\n\n const goToPage = useCallback(\n (page: number) => {\n const totalPages = result ? Math.ceil(result.totalCount / pageSize) : 0;\n if (page >= 0 && page < totalPages) {\n setCurrentPage(page);\n }\n },\n [result, pageSize]\n );\n\n return {\n records: result?.records || [],\n pagination: {\n totalCount: result?.totalCount || 0,\n hasMore: result?.hasMore || false,\n page: currentPage,\n pageSize,\n hasPrevious: currentPage > 0,\n },\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n goToNextPage,\n goToPreviousPage,\n goToPage,\n setFilters: () => {}, // No-op for pending refunds\n };\n}\n\n/**\n * Hook for fetching refund statistics\n */\nexport function useRefundStats(): UseRefundStatsResult {\n const { data, loading, error, refetch } = useGetRefundStatsQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n stats: data?.getRefundStats || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching a single refund record by ID\n */\nexport function useRefundRecord(id: string | undefined): UseRefundRecordResult {\n const { data, loading, error, refetch } = useGetRefundRecordQuery({\n variables: { id: id! },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n record: data?.getRefundRecord || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching unprocessed failed webhooks\n */\nexport function useUnprocessedFailedWebhooks(): UseUnprocessedWebhooksResult {\n const { data, loading, error, refetch } = useGetUnprocessedFailedWebhooksQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n webhooks: data?.getUnprocessedFailedWebhooks || [],\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for the admin billing-webhook-log viewer — paginated, filterable view\n * over ALL webhook log rows (unlike useUnprocessedFailedWebhooks, which only\n * scans the narrow refund-candidate subset).\n */\nexport function useBillingWebhookLogs(\n filters: BillingWebhookLogFilters,\n page: number,\n pageSize: number\n): UseBillingWebhookLogsResult {\n const { data, loading, error, refetch } = useGetBillingWebhookLogsQuery({\n variables: {\n limit: pageSize,\n offset: page * pageSize,\n processed: filters.processed,\n provider: filters.provider,\n hasError: filters.hasError,\n },\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n logs: data?.getBillingWebhookLogs.logs || [],\n totalCount: data?.getBillingWebhookLogs.totalCount || 0,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for refund mutations\n */\nexport function useRefundMutations(): UseRefundMutationsResult {\n const client = useApolloClient();\n\n const [createRefundRecordMutation, { loading: isCreating }] = useCreateRefundRecordMutation();\n const [processRefundMutation, { loading: isProcessing }] = useProcessRefundMutation();\n const [skipRefundMutation, { loading: isSkipping }] = useSkipRefundMutation();\n const [retryRefundMutation, { loading: isRetrying }] = useRetryRefundMutation();\n const [createFromWebhooksMutation, { loading: isCreatingFromWebhooks }] =\n useCreateRefundRecordsFromFailedWebhooksMutation();\n const [createFromWebhookMutation, { loading: isCreatingFromWebhook }] =\n useCreateRefundRecordFromWebhookMutation();\n\n const refetchQueries = useCallback(async () => {\n await client.refetchQueries({\n include: [GetRefundRecordsDocument, GetPendingRefundsDocument, GetRefundStatsDocument],\n });\n }, [client]);\n\n const createRefundRecord = useCallback(\n async (input: CreateRefundRecordInput): Promise<RefundRecord> => {\n const { data } = await createRefundRecordMutation({\n variables: input,\n });\n await refetchQueries();\n return data.createRefundRecord;\n },\n [createRefundRecordMutation, refetchQueries]\n );\n\n const processRefund = useCallback(\n async (id: string, notes?: string): Promise<ProcessRefundResult> => {\n const { data } = await processRefundMutation({\n variables: { id, notes },\n });\n await refetchQueries();\n return data.processRefund;\n },\n [processRefundMutation, refetchQueries]\n );\n\n const skipRefund = useCallback(\n async (id: string, reason: string): Promise<RefundRecord> => {\n const { data } = await skipRefundMutation({\n variables: { id, reason },\n });\n await refetchQueries();\n return data.skipRefund;\n },\n [skipRefundMutation, refetchQueries]\n );\n\n const retryRefund = useCallback(\n async (id: string): Promise<ProcessRefundResult> => {\n const { data } = await retryRefundMutation({\n variables: { id },\n });\n await refetchQueries();\n return data.retryRefund;\n },\n [retryRefundMutation, refetchQueries]\n );\n\n const createRefundRecordsFromFailedWebhooks = useCallback(async (): Promise<RefundRecord[]> => {\n const { data } = await createFromWebhooksMutation();\n await client.refetchQueries({\n include: [\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n GetBillingWebhookLogsDocument,\n ],\n });\n return data!.createRefundRecordsFromFailedWebhooks;\n }, [createFromWebhooksMutation, client]);\n\n const createRefundRecordFromWebhook = useCallback(\n async (webhookLogId: string): Promise<RefundRecord | null> => {\n const { data } = await createFromWebhookMutation({\n variables: { webhookLogId },\n });\n await client.refetchQueries({\n include: [\n GetRefundRecordsDocument,\n GetPendingRefundsDocument,\n GetRefundStatsDocument,\n GetUnprocessedFailedWebhooksDocument,\n ],\n });\n return data!.createRefundRecordFromWebhook;\n },\n [createFromWebhookMutation, client]\n );\n\n return {\n createRefundRecord,\n processRefund,\n skipRefund,\n retryRefund,\n createRefundRecordsFromFailedWebhooks,\n createRefundRecordFromWebhook,\n isCreating,\n isProcessing,\n isSkipping,\n isRetrying,\n isCreatingFromWebhooks,\n isCreatingFromWebhook,\n };\n}\n\n/**\n * Combined hook for refund page with all data and mutations\n */\nexport function useRefunds(options: UseRefundRecordsOptions = {}) {\n const recordsHook = useRefundRecords(options);\n const statsHook = useRefundStats();\n const mutationsHook = useRefundMutations();\n const webhooksHook = useUnprocessedFailedWebhooks();\n\n const isLoading = useMemo(\n () => recordsHook.isLoading || statsHook.isLoading,\n [recordsHook.isLoading, statsHook.isLoading]\n );\n\n const refetchAll = useCallback(async () => {\n await Promise.all([recordsHook.refetch(), statsHook.refetch(), webhooksHook.refetch()]);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Intentional: accessing stable refetch methods from hooks\n }, [recordsHook.refetch, statsHook.refetch, webhooksHook.refetch]);\n\n return {\n // Records\n records: recordsHook.records,\n pagination: recordsHook.pagination,\n goToNextPage: recordsHook.goToNextPage,\n goToPreviousPage: recordsHook.goToPreviousPage,\n goToPage: recordsHook.goToPage,\n setFilters: recordsHook.setFilters,\n\n // Stats\n stats: statsHook.stats,\n\n // Failed webhooks\n unprocessedWebhooks: webhooksHook.webhooks,\n webhooksLoading: webhooksHook.isLoading,\n\n // Loading states\n isLoading,\n recordsError: recordsHook.error,\n statsError: statsHook.error,\n\n // Mutations\n ...mutationsHook,\n\n // Refetch\n refetch: refetchAll,\n refetchRecords: recordsHook.refetch,\n refetchStats: statsHook.refetch,\n refetchWebhooks: webhooksHook.refetch,\n };\n}\n"],"mappings":";;;;AA2MA,IAAM,IAAoB;AAK1B,SAAgB,EAAiB,IAAmC,CAAC,GAA2B;CAC9F,IAAM,IAAW,EAAQ,YAAY,GAC/B,CAAC,GAAa,KAAkB,EAAS,CAAC,GAC1C,CAAC,GAAS,KAAc,EAA8B,EAAQ,WAAW,CAAC,CAAC;CAGjF,QAAgB;EAEd,AADA,EAAW,EAAQ,WAAW,CAAC,CAAC,GAChC,EAAe,CAAC;CAClB,GAAG,CAAC,EAAQ,OAAO,CAAC;CAEpB,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAyB;EACjE,WAAW;GACT,GAAG;GACH,MAAM;GACN;EACF;EACA,aAAa;CACf,CAAC,GAEK,IAAgB,EAAY,YAAY;EAC5C,MAAM,EAAQ;CAChB,GAAG,CAAC,CAAO,CAAC,GAEN,IAAS,GAAM,kBAEf,IAAe,QAAkB;EACrC,AAAI,GAAQ,WACV,GAAgB,MAAS,IAAO,CAAC;CAErC,GAAG,CAAC,GAAQ,OAAO,CAAC,GAEd,IAAmB,QAAkB;EACzC,AAAI,IAAc,KAChB,GAAgB,MAAS,IAAO,CAAC;CAErC,GAAG,CAAC,CAAW,CAAC,GAEV,IAAW,GACd,MAAiB;EAChB,IAAM,IAAa,IAAS,KAAK,KAAK,EAAO,aAAa,CAAQ,IAAI;EACtE,AAAI,KAAQ,KAAK,IAAO,KACtB,EAAe,CAAI;CAEvB,GACA,CAAC,GAAQ,CAAQ,CACnB,GAEM,IAAmB,GAAa,MAAoC;EAExE,AADA,EAAW,CAAU,GACrB,EAAe,CAAC;CAClB,GAAG,CAAC,CAAC;CAEL,OAAO;EACL,SAAS,GAAQ,WAAW,CAAC;EAC7B,YAAY;GACV,YAAY,GAAQ,cAAc;GAClC,SAAS,GAAQ,WAAW;GAC5B,MAAM;GACN;GACA,aAAa,IAAc;EAC7B;EACA,WAAW;EACJ;EACP,SAAS;EACT;EACA;EACA;EACA,YAAY;CACd;AACF;AA+DA,SAAgB,IAAuC;CACrD,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAuB,EAC/D,aAAa,oBACf,CAAC,GAEK,IAAgB,EAAY,YAAY;EAC5C,MAAM,EAAQ;CAChB,GAAG,CAAC,CAAO,CAAC;CAEZ,OAAO;EACL,OAAO,GAAM,kBAAkB;EAC/B,WAAW;EACJ;EACP,SAAS;CACX;AACF;AA2BA,SAAgB,IAA6D;CAC3E,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAAqC,EAC7E,aAAa,oBACf,CAAC,GAEK,IAAgB,EAAY,YAAY;EAC5C,MAAM,EAAQ;CAChB,GAAG,CAAC,CAAO,CAAC;CAEZ,OAAO;EACL,UAAU,GAAM,gCAAgC,CAAC;EACjD,WAAW;EACJ;EACP,SAAS;CACX;AACF;AAOA,SAAgB,EACd,GACA,GACA,GAC6B;CAC7B,IAAM,EAAE,SAAM,YAAS,UAAO,eAAY,EAA8B;EACtE,WAAW;GACT,OAAO;GACP,QAAQ,IAAO;GACf,WAAW,EAAQ;GACnB,UAAU,EAAQ;GAClB,UAAU,EAAQ;EACpB;EACA,aAAa;CACf,CAAC,GAEK,IAAgB,EAAY,YAAY;EAC5C,MAAM,EAAQ;CAChB,GAAG,CAAC,CAAO,CAAC;CAEZ,OAAO;EACL,MAAM,GAAM,sBAAsB,QAAQ,CAAC;EAC3C,YAAY,GAAM,sBAAsB,cAAc;EACtD,WAAW;EACJ;EACP,SAAS;CACX;AACF;AAKA,SAAgB,IAA+C;CAC7D,IAAM,IAAS,EAAgB,GAEzB,CAAC,GAA4B,EAAE,SAAS,OAAgB,EAA8B,GACtF,CAAC,GAAuB,EAAE,SAAS,OAAkB,EAAyB,GAC9E,CAAC,GAAoB,EAAE,SAAS,OAAgB,EAAsB,GACtE,CAAC,GAAqB,EAAE,SAAS,OAAgB,EAAuB,GACxE,CAAC,GAA4B,EAAE,SAAS,OAC5C,EAAiD,GAC7C,CAAC,GAA2B,EAAE,SAAS,OAC3C,EAAyC,GAErC,IAAiB,EAAY,YAAY;EAC7C,MAAM,EAAO,eAAe,EAC1B,SAAS;GAAC;GAA0B;GAA2B;EAAsB,EACvF,CAAC;CACH,GAAG,CAAC,CAAM,CAAC;CA8EX,OAAO;EACL,oBA7EyB,EACzB,OAAO,MAA0D;GAC/D,IAAM,EAAE,YAAS,MAAM,EAA2B,EAChD,WAAW,EACb,CAAC;GAED,OADA,MAAM,EAAe,GACd,EAAK;EACd,GACA,CAAC,GAA4B,CAAc,CAqE3C;EACA,eAnEoB,EACpB,OAAO,GAAY,MAAiD;GAClE,IAAM,EAAE,YAAS,MAAM,EAAsB,EAC3C,WAAW;IAAE;IAAI;GAAM,EACzB,CAAC;GAED,OADA,MAAM,EAAe,GACd,EAAK;EACd,GACA,CAAC,GAAuB,CAAc,CA2DtC;EACA,YAzDiB,EACjB,OAAO,GAAY,MAA0C;GAC3D,IAAM,EAAE,YAAS,MAAM,EAAmB,EACxC,WAAW;IAAE;IAAI;GAAO,EAC1B,CAAC;GAED,OADA,MAAM,EAAe,GACd,EAAK;EACd,GACA,CAAC,GAAoB,CAAc,CAiDnC;EACA,aA/CkB,EAClB,OAAO,MAA6C;GAClD,IAAM,EAAE,YAAS,MAAM,EAAoB,EACzC,WAAW,EAAE,MAAG,EAClB,CAAC;GAED,OADA,MAAM,EAAe,GACd,EAAK;EACd,GACA,CAAC,GAAqB,CAAc,CAuCpC;EACA,uCArC4C,EAAY,YAAqC;GAC7F,IAAM,EAAE,YAAS,MAAM,EAA2B;GAUlD,OATA,MAAM,EAAO,eAAe,EAC1B,SAAS;IACP;IACA;IACA;IACA;IACA;GACF,EACF,CAAC,GACM,EAAM;EACf,GAAG,CAAC,GAA4B,CAAM,CAyBpC;EACA,+BAxBoC,EACpC,OAAO,MAAuD;GAC5D,IAAM,EAAE,YAAS,MAAM,EAA0B,EAC/C,WAAW,EAAE,gBAAa,EAC5B,CAAC;GASD,OARA,MAAM,EAAO,eAAe,EAC1B,SAAS;IACP;IACA;IACA;IACA;GACF,EACF,CAAC,GACM,EAAM;EACf,GACA,CAAC,GAA2B,CAAM,CASlC;EACA;EACA;EACA;EACA;EACA;EACA;CACF;AACF;AAKA,SAAgB,EAAW,IAAmC,CAAC,GAAG;CAChE,IAAM,IAAc,EAAiB,CAAO,GACtC,IAAY,EAAe,GAC3B,IAAgB,EAAmB,GACnC,IAAe,EAA6B,GAE5C,IAAY,QACV,EAAY,aAAa,EAAU,WACzC,CAAC,EAAY,WAAW,EAAU,SAAS,CAC7C,GAEM,IAAa,EAAY,YAAY;EACzC,MAAM,QAAQ,IAAI;GAAC,EAAY,QAAQ;GAAG,EAAU,QAAQ;GAAG,EAAa,QAAQ;EAAC,CAAC;CAExF,GAAG;EAAC,EAAY;EAAS,EAAU;EAAS,EAAa;CAAO,CAAC;CAEjE,OAAO;EAEL,SAAS,EAAY;EACrB,YAAY,EAAY;EACxB,cAAc,EAAY;EAC1B,kBAAkB,EAAY;EAC9B,UAAU,EAAY;EACtB,YAAY,EAAY;EAGxB,OAAO,EAAU;EAGjB,qBAAqB,EAAa;EAClC,iBAAiB,EAAa;EAG9B;EACA,cAAc,EAAY;EAC1B,YAAY,EAAU;EAGtB,GAAG;EAGH,SAAS;EACT,gBAAgB,EAAY;EAC5B,cAAc,EAAU;EACxB,iBAAiB,EAAa;CAChC;AACF"}
@@ -8,18 +8,19 @@ import { useDashboardMutations as a, useDefaultDashboardAccount as o } from "../
8
8
  import "../../dashboard/hooks/index.js";
9
9
  import { nativeConfirm as s, nativeImpact as c, nativeNotify as l } from "../../../../utils/nativeBridge.js";
10
10
  import { AddPaymentMethodModal as u } from "../../dashboard/components/AddPaymentMethodModal.js";
11
- import { useCallback as d, useEffect as f, useState as p } from "react";
12
- import { useLocation as m } from "react-router";
13
- import { jsx as h, jsxs as g } from "react/jsx-runtime";
14
- import { useI18n as _ } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
15
- import { IllustratedEmptyState as v, PagePurpose as y } from "@burdenoff/fe-libs/ui";
11
+ import { toast as d } from "../../../../node_modules/sonner/dist/index.js";
12
+ import { useCallback as f, useEffect as p, useState as m } from "react";
13
+ import { useLocation as h } from "react-router";
14
+ import { jsx as g, jsxs as _ } from "react/jsx-runtime";
15
+ import { useI18n as v } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
16
+ import { IllustratedEmptyState as y, PagePurpose as b } from "@burdenoff/fe-libs/ui";
16
17
  //#region src/billing/modules/billing/pages/PaymentMethodsPage.tsx
17
- var b = {
18
+ var x = {
18
19
  visa: "💳",
19
20
  mastercard: "💳",
20
21
  amex: "💳",
21
22
  default: "💳"
22
- }, x = {
23
+ }, S = {
23
24
  CREDIT_CARD: "Credit Card",
24
25
  DEBIT_CARD: "Debit Card",
25
26
  WALLET: "Digital Wallet",
@@ -27,134 +28,136 @@ var b = {
27
28
  BANK_TRANSFER: "Bank Transfer",
28
29
  PAYPAL: "PayPal",
29
30
  CRYPTO: "Cryptocurrency"
30
- }, S = () => {
31
- let { t: s } = _(), c = (e, t) => {
31
+ }, C = () => {
32
+ let { t: s } = v(), c = (e, t) => {
32
33
  let n = s(e);
33
34
  return n === e ? t : n;
34
- }, b = i(), { emit: x } = r(), { navigate: S, basePath: w } = e(), { pathname: T } = m(), { billingAccount: E, paymentMethods: D, isLoading: O, refetch: k } = o(), { setDefaultPaymentMethod: A, deletePaymentMethod: j } = a(), [M, N] = p(!1), [P, F] = p(null), I = d((e) => w && w !== "/" ? `${w.endsWith("/") ? w.slice(0, -1) : w}/${e}` : `/${e}`, [w]), L = d(() => {
35
- S(I("payment-methods/add"));
36
- }, [S, I]), R = d(async (e) => {
37
- let t = E?.id;
35
+ }, x = i(), { emit: S } = r(), { navigate: C, basePath: T } = e(), { pathname: E } = h(), { billingAccount: D, paymentMethods: O, isLoading: k, refetch: A } = o(), { setDefaultPaymentMethod: j, deletePaymentMethod: M } = a(), [N, P] = m(!1), [F, I] = m(null), L = f((e) => T && T !== "/" ? `${T.endsWith("/") ? T.slice(0, -1) : T}/${e}` : `/${e}`, [T]), R = f(() => {
36
+ C(L("payment-methods/add"));
37
+ }, [C, L]), z = f(async (e) => {
38
+ let t = D?.id;
38
39
  if (!t) {
39
- F("No billing account context");
40
+ I("No billing account context");
40
41
  return;
41
42
  }
42
- F(null);
43
+ I(null);
43
44
  try {
44
- await A(e, t), await k(), l("success"), x("billing.payment_method.default_set", {
45
+ await j(e, t), await A(), l("success"), S("billing.payment_method.default_set", {
45
46
  route: "/billing/payment-methods",
46
47
  entityId: e,
47
48
  source: "payment-methods"
48
49
  });
49
50
  } catch (e) {
50
- F(e instanceof Error ? e.message : "Failed to set default payment method"), l("error");
51
+ I(e instanceof Error ? e.message : "Failed to set default payment method"), l("error");
51
52
  }
52
53
  }, [
53
- E?.id,
54
- x,
55
- k,
56
- A
57
- ]), z = d(async (e) => {
58
- let t = E?.id;
54
+ D?.id,
55
+ S,
56
+ A,
57
+ j
58
+ ]), B = f(async (e) => {
59
+ let t = D?.id;
59
60
  if (!t) {
60
- F("No billing account context");
61
+ I("No billing account context");
61
62
  return;
62
63
  }
63
- F(null);
64
+ I(null);
64
65
  try {
65
- await j(e, t), await k(), l("success"), x("billing.payment_method.deleted", {
66
+ await M(e, t), await A(), l("success"), S("billing.payment_method.deleted", {
66
67
  route: "/billing/payment-methods",
67
68
  entityId: e,
68
69
  source: "payment-methods"
69
70
  });
70
71
  } catch (e) {
71
- F(e instanceof Error ? e.message : "Failed to remove payment method"), l("error");
72
+ I(e instanceof Error ? e.message : "Failed to remove payment method"), l("error");
72
73
  }
73
74
  }, [
74
- E?.id,
75
- j,
76
- x,
77
- k
75
+ D?.id,
76
+ M,
77
+ S,
78
+ A
78
79
  ]);
79
- return f(() => {
80
- T.replace(/\/+$/, "").endsWith("/payment-methods/add") && N(!0);
81
- }, [T]), b.canViewPaymentMethods ? O ? /* @__PURE__ */ g("div", {
80
+ return p(() => {
81
+ E.replace(/\/+$/, "").endsWith("/payment-methods/add") && P(!0);
82
+ }, [E]), x.canViewPaymentMethods ? k ? /* @__PURE__ */ _("div", {
82
83
  className: "space-y-6 p-6",
83
- children: [/* @__PURE__ */ h("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ h("div", {
84
+ children: [/* @__PURE__ */ g("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ g("div", {
84
85
  className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
85
86
  children: [
86
87
  1,
87
88
  2,
88
89
  3
89
- ].map((e) => /* @__PURE__ */ h("div", { className: "h-32 bg-bg-sunken animate-pulse rounded-lg" }, e))
90
+ ].map((e) => /* @__PURE__ */ g("div", { className: "h-32 bg-bg-sunken animate-pulse rounded-lg" }, e))
90
91
  })]
91
- }) : /* @__PURE__ */ g("div", {
92
+ }) : /* @__PURE__ */ _("div", {
92
93
  className: "space-y-6 p-6",
93
94
  children: [
94
- /* @__PURE__ */ h(n, {
95
+ /* @__PURE__ */ g(n, {
95
96
  title: c("billing.paymentMethods.title", "Payment Methods"),
96
97
  description: c("billing.paymentMethods.subtitle", "Manage your saved payment methods"),
97
- actions: b.canManagePaymentMethods && /* @__PURE__ */ h("button", {
98
+ actions: x.canManagePaymentMethods && /* @__PURE__ */ g("button", {
98
99
  type: "button",
99
- onClick: L,
100
+ onClick: R,
100
101
  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",
101
102
  children: c("billing.paymentMethods.add", "Add payment method")
102
103
  })
103
104
  }),
104
- /* @__PURE__ */ h(y, { children: c("billing.paymentMethods.purpose", "Save and manage the cards and payment options used to pay invoices, subscriptions and one-off purchases. Add a method, mark one as default for automatic billing, or remove ones you no longer use.") }),
105
- P && /* @__PURE__ */ h("div", {
105
+ /* @__PURE__ */ g(b, { children: c("billing.paymentMethods.purpose", "Save and manage the cards and payment options used to pay invoices, subscriptions and one-off purchases. Add a method, mark one as default for automatic billing, or remove ones you no longer use.") }),
106
+ F && /* @__PURE__ */ g("div", {
106
107
  className: "rounded-button border border-status-error-border bg-status-error-bg-subtle p-3",
107
- children: /* @__PURE__ */ h("p", {
108
+ children: /* @__PURE__ */ g("p", {
108
109
  className: "text-sm text-status-error-text",
109
- children: P
110
+ children: F
110
111
  })
111
112
  }),
112
- D.length === 0 ? /* @__PURE__ */ h(v, {
113
+ O.length === 0 ? /* @__PURE__ */ g(y, {
113
114
  illustration: "empty-generic",
114
115
  title: c("billing.paymentMethods.noPaymentMethods", "No payment methods"),
115
116
  description: c("billing.paymentMethods.noPaymentMethodsDesc", "Add a payment method to make purchases and manage subscriptions."),
116
- action: b.canManagePaymentMethods ? /* @__PURE__ */ h("button", {
117
+ action: x.canManagePaymentMethods ? /* @__PURE__ */ g("button", {
117
118
  type: "button",
118
- onClick: () => N(!0),
119
+ onClick: () => P(!0),
119
120
  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",
120
121
  children: "Add Payment Method"
121
122
  }) : void 0
122
- }) : /* @__PURE__ */ h("div", {
123
+ }) : /* @__PURE__ */ g("div", {
123
124
  className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
124
- children: D.map((e) => /* @__PURE__ */ h(C, {
125
+ children: O.map((e) => /* @__PURE__ */ g(w, {
125
126
  method: e,
126
- canManage: b.canManagePaymentMethods,
127
- onSetDefault: R,
128
- onDelete: z
127
+ canManage: x.canManagePaymentMethods,
128
+ onSetDefault: z,
129
+ onDelete: B
129
130
  }, e.id))
130
131
  }),
131
- /* @__PURE__ */ h(u, {
132
- isOpen: M,
132
+ /* @__PURE__ */ g(u, {
133
+ isOpen: N,
133
134
  onClose: () => {
134
- N(!1), T.replace(/\/+$/, "").endsWith("/payment-methods/add") && S(I("payment-methods"));
135
+ P(!1), E.replace(/\/+$/, "").endsWith("/payment-methods/add") && C(L("payment-methods"));
135
136
  },
136
- billingAccountId: E?.id ?? "",
137
- currency: E?.currency ?? "USD",
138
- country: E?.billingAddresses?.[0]?.country ?? void 0,
137
+ billingAccountId: D?.id ?? "",
138
+ currency: D?.currency ?? "USD",
139
+ country: D?.billingAddresses?.[0]?.country ?? void 0,
139
140
  onSuccess: () => {
140
- x("billing.payment_method.added", {
141
+ S("billing.payment_method.added", {
141
142
  route: "/billing/payment-methods",
142
- entityId: E?.id,
143
+ entityId: D?.id,
143
144
  source: "payment-methods"
144
- }), F(null), k(), N(!1), T.replace(/\/+$/, "").endsWith("/payment-methods/add") && S(I("payment-methods"));
145
+ }), I(null), l("success"), d.success("Payment method added successfully"), P(!1), E.replace(/\/+$/, "").endsWith("/payment-methods/add") && C(L("payment-methods")), A(), setTimeout(() => {
146
+ A();
147
+ }, 2500);
145
148
  }
146
149
  })
147
150
  ]
148
- }) : /* @__PURE__ */ h(t, { message: c("billing.paymentMethods.noViewPermission", "You don't have permission to view payment methods.") });
149
- }, C = ({ method: e, canManage: t, onSetDefault: n, onDelete: r }) => {
150
- let [i, a] = p(!1), [o, l] = p(!1), [u, d] = p(!1), f = e.expiryYear && e.expiryMonth ? new Date(e.expiryYear, e.expiryMonth - 1) < /* @__PURE__ */ new Date() : !1, m = async () => {
151
+ }) : /* @__PURE__ */ g(t, { message: c("billing.paymentMethods.noViewPermission", "You don't have permission to view payment methods.") });
152
+ }, w = ({ method: e, canManage: t, onSetDefault: n, onDelete: r }) => {
153
+ let [i, a] = m(!1), [o, l] = m(!1), [u, d] = m(!1), f = e.expiryYear && e.expiryMonth ? new Date(e.expiryYear, e.expiryMonth - 1) < /* @__PURE__ */ new Date() : !1, p = async () => {
151
154
  a(!0);
152
155
  try {
153
156
  await n(e.id);
154
157
  } finally {
155
158
  a(!1);
156
159
  }
157
- }, _ = async () => {
160
+ }, h = async () => {
158
161
  l(!0);
159
162
  try {
160
163
  await r(e.id);
@@ -162,30 +165,30 @@ var b = {
162
165
  l(!1), d(!1);
163
166
  }
164
167
  };
165
- return /* @__PURE__ */ g("div", {
168
+ return /* @__PURE__ */ _("div", {
166
169
  className: `border rounded-lg bg-bg-surface p-4 ${e.isDefault ? "border-primary" : "border-border-subtle"}`,
167
170
  children: [
168
- /* @__PURE__ */ h("div", {
171
+ /* @__PURE__ */ g("div", {
169
172
  className: "flex items-start justify-between",
170
- children: /* @__PURE__ */ g("div", {
173
+ children: /* @__PURE__ */ _("div", {
171
174
  className: "flex items-center gap-3",
172
- children: [/* @__PURE__ */ h("span", {
175
+ children: [/* @__PURE__ */ g("span", {
173
176
  className: "text-2xl",
174
- children: b[e.brand?.toLowerCase() ?? "default"]
175
- }), /* @__PURE__ */ g("div", { children: [/* @__PURE__ */ g("div", {
177
+ children: x[e.brand?.toLowerCase() ?? "default"]
178
+ }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("div", {
176
179
  className: "flex items-center gap-2",
177
- children: [/* @__PURE__ */ g("p", {
180
+ children: [/* @__PURE__ */ _("p", {
178
181
  className: "font-medium text-text-primary",
179
182
  children: [
180
- e.brand ?? x[e.type],
183
+ e.brand ?? S[e.type],
181
184
  " •••• ",
182
185
  e.last4
183
186
  ]
184
- }), e.isDefault && /* @__PURE__ */ h("span", {
187
+ }), e.isDefault && /* @__PURE__ */ g("span", {
185
188
  className: "px-1.5 py-0.5 text-xs font-medium bg-action-primary-bg/10 text-primary rounded",
186
189
  children: "Default"
187
190
  })]
188
- }), e.expiryMonth && e.expiryYear && /* @__PURE__ */ g("p", {
191
+ }), e.expiryMonth && e.expiryYear && /* @__PURE__ */ _("p", {
189
192
  className: `text-sm ${f ? "text-status-error-text" : "text-text-secondary"}`,
190
193
  children: [
191
194
  f ? "Expired" : "Expires",
@@ -197,15 +200,15 @@ var b = {
197
200
  })] })]
198
201
  })
199
202
  }),
200
- t && /* @__PURE__ */ g("div", {
203
+ t && /* @__PURE__ */ _("div", {
201
204
  className: "flex items-center gap-2 mt-4 pt-4 border-t border-border-subtle",
202
- children: [!e.isDefault && /* @__PURE__ */ h("button", {
205
+ children: [!e.isDefault && /* @__PURE__ */ g("button", {
203
206
  type: "button",
204
- onClick: m,
207
+ onClick: p,
205
208
  disabled: i || o,
206
209
  className: "text-sm text-primary hover:underline disabled:cursor-not-allowed disabled:opacity-50",
207
210
  children: i ? "Setting default…" : "Set as default"
208
- }), /* @__PURE__ */ h("button", {
211
+ }), /* @__PURE__ */ g("button", {
209
212
  type: "button",
210
213
  onClick: async () => {
211
214
  c("medium");
@@ -215,28 +218,28 @@ var b = {
215
218
  okButtonTitle: "Delete",
216
219
  cancelButtonTitle: "Cancel"
217
220
  });
218
- e === !0 ? await _() : e === null && d(!0);
221
+ e === !0 ? await h() : e === null && d(!0);
219
222
  },
220
223
  disabled: i || o,
221
224
  className: "text-sm text-status-error-text hover:underline ml-auto disabled:cursor-not-allowed disabled:opacity-50",
222
225
  children: o ? "Removing…" : "Remove"
223
226
  })]
224
227
  }),
225
- u && /* @__PURE__ */ g("div", {
228
+ u && /* @__PURE__ */ _("div", {
226
229
  className: "mt-4 rounded-lg border border-status-error-border bg-status-error-bg-subtle p-3",
227
- children: [/* @__PURE__ */ h("p", {
230
+ children: [/* @__PURE__ */ g("p", {
228
231
  className: "text-sm font-medium text-status-error-text",
229
232
  children: "Remove this payment method from your billing account?"
230
- }), /* @__PURE__ */ g("div", {
233
+ }), /* @__PURE__ */ _("div", {
231
234
  className: "mt-3 flex justify-end gap-2",
232
- children: [/* @__PURE__ */ h("button", {
235
+ children: [/* @__PURE__ */ g("button", {
233
236
  type: "button",
234
237
  onClick: () => d(!1),
235
238
  className: "rounded-button border border-border-subtle bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
236
239
  children: "Cancel"
237
- }), /* @__PURE__ */ h("button", {
240
+ }), /* @__PURE__ */ g("button", {
238
241
  type: "button",
239
- onClick: _,
242
+ onClick: h,
240
243
  disabled: o,
241
244
  className: "rounded-button bg-action-danger-bg px-3 py-2 text-sm font-medium text-action-primary-text transition-colors hover:bg-action-danger-bgHover disabled:cursor-not-allowed disabled:opacity-50",
242
245
  children: o ? "Removing…" : "Remove"
@@ -247,6 +250,6 @@ var b = {
247
250
  });
248
251
  };
249
252
  //#endregion
250
- export { S as PaymentMethodsPage };
253
+ export { C as PaymentMethodsPage };
251
254
 
252
255
  //# sourceMappingURL=PaymentMethodsPage.js.map