@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.
- package/dist/billing/BillingAdminRoutes.js +84 -71
- package/dist/billing/BillingAdminRoutes.js.map +1 -1
- package/dist/billing/modules/billing/hooks/useRefunds.js.map +1 -1
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +90 -87
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/RefundIssueLogsPage.js +97 -58
- package/dist/billing/modules/billing/pages/RefundIssueLogsPage.js.map +1 -1
- package/dist/billing/modules/checkout/components/OrderSummary.js +22 -19
- package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
- package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
- package/dist/billing/modules/checkout/components/StoreShippingSection.js +191 -177
- package/dist/billing/modules/checkout/components/StoreShippingSection.js.map +1 -1
- package/dist/billing/modules/checkout/hooks/useCheckout.js +174 -157
- package/dist/billing/modules/checkout/hooks/useCheckout.js.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +191 -184
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +293 -274
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +140 -250
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
- package/dist/billing/modules/earnings/api.js +79 -42
- package/dist/billing/modules/earnings/api.js.map +1 -1
- package/dist/billing/modules/earnings/index.js +4 -3
- package/dist/billing/modules/earnings/pages/DeveloperRevenueAdminPage.js +103 -310
- package/dist/billing/modules/earnings/pages/DeveloperRevenueAdminPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/DeveloperRevenueOrgDetailPage.js +545 -0
- package/dist/billing/modules/earnings/pages/DeveloperRevenueOrgDetailPage.js.map +1 -0
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +246 -196
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js +44 -28
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +317 -270
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +153 -150
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +1 -1
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
- package/dist/billing/modules/usage/hooks/useUsage.js +74 -48
- package/dist/billing/modules/usage/hooks/useUsage.js.map +1 -1
- package/dist/generated/global-operations.js +220 -183
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/node_modules/sonner/dist/index.js +163 -0
- package/dist/node_modules/sonner/dist/index.js.map +1 -0
- 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":";;;;AAuMA,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"}
|
|
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":"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"}
|
|
@@ -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 {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
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
|
|
18
|
+
var x = {
|
|
18
19
|
visa: "💳",
|
|
19
20
|
mastercard: "💳",
|
|
20
21
|
amex: "💳",
|
|
21
22
|
default: "💳"
|
|
22
|
-
},
|
|
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
|
-
},
|
|
31
|
-
let { t: s } =
|
|
31
|
+
}, C = () => {
|
|
32
|
+
let { t: s } = v(), c = (e, t) => {
|
|
32
33
|
let n = s(e);
|
|
33
34
|
return n === e ? t : n;
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
}, [
|
|
37
|
-
let t =
|
|
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
|
-
|
|
40
|
+
I("No billing account context");
|
|
40
41
|
return;
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
I(null);
|
|
43
44
|
try {
|
|
44
|
-
await
|
|
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
|
-
|
|
51
|
+
I(e instanceof Error ? e.message : "Failed to set default payment method"), l("error");
|
|
51
52
|
}
|
|
52
53
|
}, [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
]),
|
|
58
|
-
let t =
|
|
54
|
+
D?.id,
|
|
55
|
+
S,
|
|
56
|
+
A,
|
|
57
|
+
j
|
|
58
|
+
]), B = f(async (e) => {
|
|
59
|
+
let t = D?.id;
|
|
59
60
|
if (!t) {
|
|
60
|
-
|
|
61
|
+
I("No billing account context");
|
|
61
62
|
return;
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
+
I(null);
|
|
64
65
|
try {
|
|
65
|
-
await
|
|
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
|
-
|
|
72
|
+
I(e instanceof Error ? e.message : "Failed to remove payment method"), l("error");
|
|
72
73
|
}
|
|
73
74
|
}, [
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
D?.id,
|
|
76
|
+
M,
|
|
77
|
+
S,
|
|
78
|
+
A
|
|
78
79
|
]);
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
}, [
|
|
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__ */
|
|
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__ */
|
|
90
|
+
].map((e) => /* @__PURE__ */ g("div", { className: "h-32 bg-bg-sunken animate-pulse rounded-lg" }, e))
|
|
90
91
|
})]
|
|
91
|
-
}) : /* @__PURE__ */
|
|
92
|
+
}) : /* @__PURE__ */ _("div", {
|
|
92
93
|
className: "space-y-6 p-6",
|
|
93
94
|
children: [
|
|
94
|
-
/* @__PURE__ */
|
|
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:
|
|
98
|
+
actions: x.canManagePaymentMethods && /* @__PURE__ */ g("button", {
|
|
98
99
|
type: "button",
|
|
99
|
-
onClick:
|
|
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__ */
|
|
105
|
-
|
|
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__ */
|
|
108
|
+
children: /* @__PURE__ */ g("p", {
|
|
108
109
|
className: "text-sm text-status-error-text",
|
|
109
|
-
children:
|
|
110
|
+
children: F
|
|
110
111
|
})
|
|
111
112
|
}),
|
|
112
|
-
|
|
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:
|
|
117
|
+
action: x.canManagePaymentMethods ? /* @__PURE__ */ g("button", {
|
|
117
118
|
type: "button",
|
|
118
|
-
onClick: () =>
|
|
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__ */
|
|
123
|
+
}) : /* @__PURE__ */ g("div", {
|
|
123
124
|
className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4",
|
|
124
|
-
children:
|
|
125
|
+
children: O.map((e) => /* @__PURE__ */ g(w, {
|
|
125
126
|
method: e,
|
|
126
|
-
canManage:
|
|
127
|
-
onSetDefault:
|
|
128
|
-
onDelete:
|
|
127
|
+
canManage: x.canManagePaymentMethods,
|
|
128
|
+
onSetDefault: z,
|
|
129
|
+
onDelete: B
|
|
129
130
|
}, e.id))
|
|
130
131
|
}),
|
|
131
|
-
/* @__PURE__ */
|
|
132
|
-
isOpen:
|
|
132
|
+
/* @__PURE__ */ g(u, {
|
|
133
|
+
isOpen: N,
|
|
133
134
|
onClose: () => {
|
|
134
|
-
|
|
135
|
+
P(!1), E.replace(/\/+$/, "").endsWith("/payment-methods/add") && C(L("payment-methods"));
|
|
135
136
|
},
|
|
136
|
-
billingAccountId:
|
|
137
|
-
currency:
|
|
138
|
-
country:
|
|
137
|
+
billingAccountId: D?.id ?? "",
|
|
138
|
+
currency: D?.currency ?? "USD",
|
|
139
|
+
country: D?.billingAddresses?.[0]?.country ?? void 0,
|
|
139
140
|
onSuccess: () => {
|
|
140
|
-
|
|
141
|
+
S("billing.payment_method.added", {
|
|
141
142
|
route: "/billing/payment-methods",
|
|
142
|
-
entityId:
|
|
143
|
+
entityId: D?.id,
|
|
143
144
|
source: "payment-methods"
|
|
144
|
-
}),
|
|
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__ */
|
|
149
|
-
},
|
|
150
|
-
let [i, a] =
|
|
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
|
-
},
|
|
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__ */
|
|
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__ */
|
|
171
|
+
/* @__PURE__ */ g("div", {
|
|
169
172
|
className: "flex items-start justify-between",
|
|
170
|
-
children: /* @__PURE__ */
|
|
173
|
+
children: /* @__PURE__ */ _("div", {
|
|
171
174
|
className: "flex items-center gap-3",
|
|
172
|
-
children: [/* @__PURE__ */
|
|
175
|
+
children: [/* @__PURE__ */ g("span", {
|
|
173
176
|
className: "text-2xl",
|
|
174
|
-
children:
|
|
175
|
-
}), /* @__PURE__ */
|
|
177
|
+
children: x[e.brand?.toLowerCase() ?? "default"]
|
|
178
|
+
}), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ _("div", {
|
|
176
179
|
className: "flex items-center gap-2",
|
|
177
|
-
children: [/* @__PURE__ */
|
|
180
|
+
children: [/* @__PURE__ */ _("p", {
|
|
178
181
|
className: "font-medium text-text-primary",
|
|
179
182
|
children: [
|
|
180
|
-
e.brand ??
|
|
183
|
+
e.brand ?? S[e.type],
|
|
181
184
|
" •••• ",
|
|
182
185
|
e.last4
|
|
183
186
|
]
|
|
184
|
-
}), e.isDefault && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
205
|
+
children: [!e.isDefault && /* @__PURE__ */ g("button", {
|
|
203
206
|
type: "button",
|
|
204
|
-
onClick:
|
|
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__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
233
|
+
}), /* @__PURE__ */ _("div", {
|
|
231
234
|
className: "mt-3 flex justify-end gap-2",
|
|
232
|
-
children: [/* @__PURE__ */
|
|
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__ */
|
|
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 {
|
|
253
|
+
export { C as PaymentMethodsPage };
|
|
251
254
|
|
|
252
255
|
//# sourceMappingURL=PaymentMethodsPage.js.map
|