@withpotter/lib 0.13.0-next.89 → 0.13.0-next.91

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.
@@ -307,6 +307,20 @@ export interface PlatformCockpit {
307
307
  };
308
308
  };
309
309
  }
310
+ /**
311
+ * What one payment channel (Card, USSD, Bank transfer, Opay...) brought in, in one
312
+ * currency. `amountMinor` is in minor units. Sent only by a box that records how
313
+ * customers paid; others answer 404, and the panels that use it stay hidden.
314
+ */
315
+ export interface GatewayChannelTotal {
316
+ channel: {
317
+ key: string;
318
+ label: string;
319
+ };
320
+ currency: string;
321
+ count: number;
322
+ amountMinor: string;
323
+ }
310
324
  export interface PlatformRevenue {
311
325
  range: {
312
326
  startDate: string;
@@ -865,6 +879,12 @@ export declare const platformAdminApi: {
865
879
  success: boolean;
866
880
  }>;
867
881
  overview: () => Promise<PlatformOverview>;
882
+ gatewayChannels: (params?: {
883
+ startDate?: string;
884
+ endDate?: string;
885
+ }) => Promise<{
886
+ byChannel: GatewayChannelTotal[];
887
+ }>;
868
888
  cockpit: (params?: {
869
889
  startDate?: string;
870
890
  endDate?: string;
package/dist/admin-api.js CHANGED
@@ -28,6 +28,15 @@ const platformAdminApi = {
28
28
  body: JSON.stringify({ currentPassword, newPassword })
29
29
  }),
30
30
  overview: () => apiFetch("/platform-admin/v1/overview"),
31
+ gatewayChannels: (params = {}) => {
32
+ const qs = new URLSearchParams();
33
+ if (params.startDate) qs.set("startDate", params.startDate);
34
+ if (params.endDate) qs.set("endDate", params.endDate);
35
+ const q = qs.toString();
36
+ return apiFetch(
37
+ `/platform-admin/v1/gateway-payments/channels${q ? `?${q}` : ""}`
38
+ );
39
+ },
31
40
  cockpit: (params = {}) => {
32
41
  const qs = new URLSearchParams();
33
42
  if (params.startDate) qs.set("startDate", params.startDate);
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/admin-api.ts"],"sourcesContent":["import {\n apiFetch,\n type DashboardStats,\n type FinanceAnalytics,\n type Transaction,\n} from './api';\n\nexport type {\n AccountRow,\n AccountsPage,\n AccountTenantRow,\n AccountSession,\n AccountStage,\n AccountKycStatus,\n TenantTeamMember,\n AccountsAnalytics,\n} from './admin-account-types';\nimport type {\n AccountRow,\n AccountSession,\n AccountStage,\n AccountsPage,\n AccountTenantRow,\n TenantTeamMember,\n AccountsAnalytics,\n} from './admin-account-types';\nimport type { TenantSetup } from './admin-tenant-setup-types';\nimport type { CountryFields } from './admin-country-api';\nimport { tenantsQuery, type TenantListParams } from './admin-tenants-query';\nimport type { AccountOfficer } from './admin-account-officer-api';\nimport type {\n CurrencyAmount,\n CurrencyGmvKpi,\n CurrencyOverdue,\n CurrencyPerformance,\n CurrencyRevenueGmv,\n CurrencyRevenueQuality,\n CurrencySeries,\n CurrencySettlementSummary,\n CurrencyTopTenants,\n CurrencyTotals,\n FinanceByCurrency,\n TenantCurrencyMetrics,\n} from './admin-currency-types';\nexport type * from './admin-currency-types';\n\nexport type { DashboardStats, FinanceAnalytics, Transaction } from './api';\n\n/** A merchant's finance dashboard as the admin API sends it: per currency too. */\nexport type AdminFinanceAnalytics = FinanceAnalytics & FinanceByCurrency;\n\nexport interface TenantTransactionsPage {\n transactions: Transaction[];\n pagination: {\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n };\n}\n\n// ============================================\n// PLATFORM ADMIN API (growth cockpit)\n// Cross-tenant aggregates — admin/superadmin only.\n// ============================================\n\nexport interface PlatformOverview {\n tenants: { total: number; active: number; new30d: number; new7d: number };\n accounts: { total: number; new30d: number };\n orders: { total: number; gmv: number; gmv30d: number };\n subscriptions: { active: number; trialing: number };\n growth: { tenantSeries: Array<{ date: string; count: number }> };\n}\n\nexport interface TenantsAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n tenants: number;\n accounts: number;\n avgTenantsPerAccount: number;\n activeRate: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvInRange: number;\n ordersInRange: number;\n newTenantsInRange: number;\n };\n statusBreakdown: Array<{ status: string; count: number }>;\n industryBreakdown: Array<{ industry: string; count: number }>;\n onboardingSeries: Array<{ date: string; count: number }>;\n performanceSeries: Array<{ date: string; gmv: number; orders: number }>;\n /** Absent until the matching api deploy lands — guard with `?? []`. */\n previousOnboardingSeries?: Array<{ date: string; count: number }>;\n previousPerformanceSeries?: Array<{\n date: string;\n gmv: number;\n orders: number;\n }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n /** @deprecated adds currencies together, not converted. */\n baseCurrency: string;\n /** @deprecated never convert with these. */\n rates: Record<string, number>;\n currencies?: string[];\n totalsByCurrency?: CurrencyTotals[];\n performanceSeriesByCurrency?: CurrencySeries[];\n topTenantsByCurrency?: CurrencyTopTenants[];\n}\n\nexport interface CockpitKpi {\n current: number;\n previous: number;\n pct: number | null;\n}\n\ninterface AttentionTenantRef {\n id: string;\n businessName: string;\n slug: string;\n}\n\nexport interface PlatformCockpit {\n range: { startDate: string; endDate: string };\n // Base currency all monetary figures are expressed in (USD). `rates` maps a\n // currency code to its rate-to-USD, so the client can render figures in a\n // chosen display currency by dividing a USD amount by the target's rate.\n baseCurrency: string;\n rates: Record<string, number>;\n /** Currencies with money in this payload, A→Z. */\n currencies?: string[];\n topTenantsByCurrency?: CurrencyTopTenants[];\n kpis: {\n newTenants: CockpitKpi;\n newAccounts: CockpitKpi;\n /** @deprecated adds currencies together; use `gmvByCurrency`. */\n gmv: CockpitKpi;\n orders: CockpitKpi;\n gmvByCurrency?: CurrencyGmvKpi[];\n };\n totals: {\n totalTenants: number;\n activeTenants: number;\n totalAccounts: number;\n activeSubscriptions: number;\n trialingSubscriptions: number;\n /** @deprecated adds currencies together; use `lifetimeGmvByCurrency`. */\n lifetimeGmv: number;\n lifetimeGmvByCurrency?: CurrencyAmount[];\n /**\n * Platform fees collected on card payments, one row per currency. Absent\n * until the api serves it; the Overview shows no card without it.\n */\n gatewayFeesByCurrency?: CurrencyAmount[];\n /**\n * Wallets whose business passed KYC / KYB. Absent until the api serves\n * it; the Overview shows no card without it.\n */\n verifiedWallets?: number;\n };\n sparklines: {\n tenants: number[];\n accounts: number[];\n gmv: number[];\n orders: number[];\n };\n statusBreakdown: Array<{ status: string; count: number }>;\n industryBreakdown: Array<{ industry: string; count: number }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n health?: {\n mrr: number;\n newMrr: number;\n churnedMrr: number;\n netNewMrr: number;\n grossMrrChurnPct: number;\n grossRevenueRetentionPct: number;\n newLogos: number;\n churnedLogos: number;\n netNewLogos: number;\n logoChurnPct: number;\n activePayingLogos: number;\n gmvConcentrationTop10Pct: number;\n };\n performance?: {\n takeRatePct: number | null;\n annualizedGmvRunRate: number;\n gmvPerActiveTenant: number;\n revenuePerActiveTenant: number;\n transactingTenants: number;\n transactingTenantRatePct: number;\n gmvGrowthPct: number | null;\n ordersGrowthPct: number | null;\n netNewLogos: number;\n byCurrency?: CurrencyPerformance[];\n };\n verticals?: Array<{\n industry: string;\n tenants: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvGrowthPct: number | null;\n share: number;\n }>;\n /** GMV/orders across every service Box offers (sell-products, event-tickets, …). */\n salesByService?: Array<{\n service: string;\n merchants: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvGrowthPct: number | null;\n share: number;\n }>;\n activation?: {\n funnel: Array<{ stage: string; count: number }>;\n medianDaysToFirstOrder: number | null;\n activationRatePct: number;\n orderConversionPct: number;\n };\n accounts?: {\n total: number;\n active: number;\n suspended: number;\n verified: number;\n unverifiedEmail: number;\n neverLoggedIn: number;\n dormant: number;\n new: number;\n };\n trend: {\n performanceSeries: Array<{ date: string; gmv: number; orders: number }>;\n onboardingSeries: Array<{ date: string; count: number }>;\n /** Absent until the matching api deploy lands — guard with `?? []`. */\n previousPerformanceSeries?: Array<{\n date: string;\n gmv: number;\n orders: number;\n }>;\n previousOnboardingSeries?: Array<{ date: string; count: number }>;\n performanceSeriesByCurrency?: CurrencySeries[];\n };\n attention: {\n /**\n * Feeds whose query failed; their counts are placeholders, not zeros.\n * Absent when talking to an API that predates this field.\n */\n unavailable?: Array<\n 'needsReview' | 'dormantTenants' | 'overdueInvoices' | 'failedSettlements'\n >;\n trialsEndingSoon: Array<\n AttentionTenantRef & { trialEndsAt: string; daysLeft: number }\n >;\n needsReview: Array<\n AttentionTenantRef & { status: string; createdAt: string }\n >;\n dormantTenants: Array<AttentionTenantRef & { createdAt: string }>;\n overdueInvoices: {\n count: number;\n /** @deprecated adds currencies together; use `totalByCurrency`. */\n total: number;\n totalByCurrency?: CurrencyOverdue[];\n sample: Array<{\n id: string;\n invoiceNumber: string;\n tenantId: string;\n tenantName: string;\n customerName: string | null;\n amountDue: number;\n currency: string;\n dueDate: string | null;\n }>;\n };\n failedSettlements: {\n count: number;\n sample: Array<{\n id: string;\n tenantId: string;\n tenantName: string;\n netAmount: number;\n currency: string;\n createdAt: string;\n }>;\n };\n };\n}\n\nexport interface PlatformRevenue {\n range: { startDate: string; endDate: string };\n currency: string;\n /**\n * What Olive keeps from payouts, settlements and subscription charges: net\n * credits on the ledger's platform fees account, in major units, one row per\n * currency, A to Z. Empty when nothing was earned. Not card fees only, no\n * refund netting, and test merchants are included. Absent until the api\n * serves it, so the UI hides the figure rather than showing a zero.\n */\n platformFeesEarnedByCurrency?: CurrencyAmount[];\n recurring: {\n /** False when no billing source feeds the figures below (all are 0). */\n tracked?: boolean;\n mrr: number;\n arr: number;\n arpa: number;\n activeSubscriptions: number;\n trialingSubscriptions: number;\n pastDueSubscriptions: number;\n nonRenewingSubscriptions: number;\n cancelledSubscriptions: number;\n newInRange: number;\n churnedInRange: number;\n planBreakdown: Array<{\n planId: string;\n name: string;\n interval: string;\n subscribers: number;\n mrr: number;\n }>;\n };\n gmv: {\n lifetime: number;\n inRange: number;\n ordersInRange: number;\n aov: number;\n series: Array<{ date: string; gmv: number; orders: number }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n };\n quality?: {\n quickRatio: number | null;\n nrrPct: number | null;\n expansionMrr: number;\n contractionMrr: number;\n mrrChurnRatePct: number | null;\n logoChurnRatePct: number | null;\n grossGmv: number;\n refundedGmv: number;\n netGmv: number;\n refundRatePct: number;\n refundedOrders: number;\n cohorts: Array<{\n cohort: string;\n size: number;\n retention: Array<number | null>;\n }>;\n gmvByCurrency?: CurrencyRevenueQuality[];\n };\n /** @deprecated never convert with these. */\n rates: Record<string, number>;\n currencies?: string[];\n gmvByCurrency?: CurrencyRevenueGmv[];\n}\n\nexport type TenantStatus = 'active' | 'suspended' | 'pending' | 'deleted';\n\nexport interface TenantRow extends CountryFields {\n id: string;\n slug: string;\n businessName: string;\n status: TenantStatus;\n industryKey: string | null;\n createdAt: string;\n /** The business's contact email (absent on older APIs). */\n email?: string | null;\n phone?: string | null;\n /** The owner's sign-in email. */\n ownerEmail?: string | null;\n /** @deprecated adds currencies together; use `gmvByCurrency`. */\n gmv: number;\n gmvByCurrency?: CurrencyAmount[];\n /** The merchant's account officer (absent on older APIs). */\n accountOfficer?: Pick<AccountOfficer, 'id' | 'name'> | null;\n}\n\nexport interface TenantsPage {\n rows: TenantRow[];\n total: number;\n page: number;\n pageSize: number;\n}\n\nexport interface TenantActivityOrder {\n id: string;\n orderNumber: string;\n total: number;\n currency: string;\n status: string;\n paymentStatus: string;\n customerEmail: string;\n customerName: string | null;\n createdAt: string;\n}\n\nexport interface TenantDetail extends TenantSetup {\n /** Who runs the workspace and how to reach it (absent on older APIs). */\n contact?: { email: string | null; phone: string | null };\n owner?: TenantTeamMember | null;\n team?: TenantTeamMember[];\n /** The admin in charge of this merchant (absent on older APIs). */\n accountOfficer?: AccountOfficer | null;\n id: string;\n slug: string;\n businessName: string;\n status: TenantStatus;\n industryKey: string | null;\n customDomain: string | null;\n createdAt: string;\n chargeBearer: 'merchant' | 'customer';\n currency: string;\n metrics: {\n totalOrders: number;\n paidOrders: number;\n pendingOrders: number;\n gmv: number;\n gmv30d: number;\n gmv7d: number;\n aov: number;\n totalCustomers: number;\n subscriptionStatus: string | null;\n window: {\n startDate: string;\n endDate: string;\n gmv: number;\n orders: number;\n paidOrders: number;\n aov: number;\n customers: number;\n };\n byCurrency?: TenantCurrencyMetrics[];\n };\n /** Currencies with paid orders, A→Z. */\n currencies?: string[];\n revenueSeries: Array<{ date: string; amount: number }>;\n revenueSeriesByCurrency?: Array<{\n currency: string;\n series: Array<{ date: string; amount: number }>;\n }>;\n recentOrders: TenantActivityOrder[];\n}\n\n// ---- Iteration 3: tenant cockpit domains ----\n\nexport interface TenantCustomer {\n id: string;\n email: string;\n phone: string | null;\n name: string | null;\n type: string;\n source: string | null;\n status: string;\n emailVerified: boolean;\n totalOrders: number;\n totalSpent: number;\n lastOrderAt: string | null;\n createdAt: string;\n}\n\nexport interface TenantCustomersPage {\n members: TenantCustomer[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\nexport interface TenantProduct {\n id: string;\n type: string;\n slug: string;\n title: string;\n category: string | null;\n tags: string[];\n featured: boolean;\n isActive: boolean;\n image?: { url: string } | null;\n price: number | null;\n compareAtPrice: number | null;\n currency: string | null;\n trackInventory: boolean;\n quantity: number | null;\n reserved: number | null;\n lowStockThreshold: number | null;\n createdAt: string;\n}\n\nexport interface TenantProductStats {\n total: number;\n active: number;\n featured: number;\n lowStock: number;\n outOfStock: number;\n}\n\nexport interface TenantProductsData {\n items: TenantProduct[];\n total: number;\n stats: TenantProductStats;\n}\n\nexport interface ProductRef {\n id: string;\n title: string;\n}\n\nexport interface SellerRow {\n id: string;\n title: string;\n units: number;\n revenue: number;\n}\n\nexport interface CategorySlice {\n category: string;\n count: number;\n value: number;\n}\n\nexport interface ProductInsights {\n currency: string;\n totalProducts: number;\n activeProducts: number;\n featuredProducts: number;\n lowStock: number;\n outOfStock: number;\n trackedProducts: number;\n catalogValue: number;\n inventoryValue: number;\n inventoryAtRiskValue: number;\n avgPrice: number;\n medianPrice: number;\n totalUnitsSold: number;\n totalRevenue: number;\n pctEverSold: number;\n deadStock: number;\n newestProduct: (ProductRef & { createdAt: string }) | null;\n lastUpdatedProduct: (ProductRef & { updatedAt: string }) | null;\n categories: CategorySlice[];\n bestSellers: SellerRow[];\n worstSellers: SellerRow[];\n featuredSellThrough: {\n featuredTotal: number;\n featuredSold: number;\n featuredUnits: number;\n nonFeaturedTotal: number;\n nonFeaturedSold: number;\n nonFeaturedUnits: number;\n };\n unitsSeries: Array<{ date: string; count: number }>;\n}\n\nexport interface SpenderRow {\n id: string;\n name: string | null;\n email: string;\n totalSpent: number;\n totalOrders: number;\n}\n\nexport interface BreakdownSlice {\n label: string;\n count: number;\n}\n\nexport interface CustomerInsights {\n currency: string;\n totalCustomers: number;\n newCustomers30d: number;\n payingCustomers: number;\n repeatCustomers: number;\n repeatRate: number;\n dormantCustomers: number;\n marketingOptInRate: number;\n lifetimeValue: number;\n avgSpendPerCustomer: number;\n avgOrdersPerCustomer: number;\n avgOrderValue: number;\n topSpenders: SpenderRow[];\n bySource: BreakdownSlice[];\n byType: BreakdownSlice[];\n signupsSeries: Array<{ date: string; count: number }>;\n}\n\nexport interface TenantInvoice {\n id: string;\n invoiceNumber: string;\n status: string;\n customerEmail: string | null;\n customerName: string | null;\n total: number;\n amountPaid: number;\n amountDue: number;\n currency: string;\n dueDate: string | null;\n createdAt: string;\n}\n\nexport interface TenantInvoiceStats {\n draft: number;\n sent: number;\n paid: number;\n overdue: number;\n cancelled: number;\n total: number;\n totalRevenue: number;\n totalOutstanding: number;\n}\n\nexport interface TenantInvoicesData {\n invoices: TenantInvoice[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n stats: TenantInvoiceStats;\n}\n\nexport interface TenantLoyaltyProgram {\n id: string;\n name: string;\n pointsName: string;\n pointsPerCurrency: number;\n currencyPerPoint: number;\n isActive: boolean;\n tiers?: Array<{ id: string; name: string; threshold: number }>;\n earnRules?: Array<{ id: string; name: string; points: number }>;\n}\n\nexport interface TenantLoyaltyStats {\n totalMembers: number;\n totalPointsIssued: number;\n totalPointsRedeemed: number;\n activeMembers: number;\n programActive: boolean;\n}\n\nexport interface TenantLoyaltyData {\n program: TenantLoyaltyProgram | null;\n stats: TenantLoyaltyStats;\n}\n\nexport interface TenantDiscount {\n id: string;\n name: string;\n code: string;\n discountType: string;\n value: number;\n maxDiscountAmount: number | null;\n startsAt: string | null;\n endsAt: string | null;\n usageLimit: number | null;\n usageCount: number;\n status: string;\n autoApply: boolean;\n isValid: boolean;\n isExpired: boolean;\n createdAt: string;\n}\n\nexport interface TenantDiscountsPage {\n discounts: TenantDiscount[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\nexport interface TenantSettlement {\n id: string;\n grossAmount: number;\n paystackFee: number;\n platformFee: number;\n netAmount: number;\n currency: string;\n status: string;\n settlementType: string;\n bankAccount?: { bankName: string; accountNumber: string } | null;\n settledAt: string | null;\n createdAt: string;\n}\n\nexport interface TenantSettlementSummary {\n totalSettled: number;\n totalPending: number;\n totalFailed: number;\n count: number;\n platformFeesCollected: number;\n currency: string;\n currencies?: string[];\n byCurrency?: CurrencySettlementSummary[];\n}\n\nexport interface TenantBankAccount {\n id: string;\n bankCode: string;\n bankName: string;\n accountNumber: string;\n accountName: string;\n splitPercentage: number | null;\n status: string;\n isDefault: boolean;\n /** Paystack subaccount code (ACCT_…). */\n subaccountCode?: string | null;\n failureReason?: string | null;\n createdAt: string;\n}\n\nexport interface TenantSettlementsData {\n settlements: TenantSettlement[];\n total: number;\n page: number;\n limit: number;\n summary: TenantSettlementSummary;\n bankAccounts: TenantBankAccount[];\n}\n\nexport interface TenantSubscriptionPlan {\n id: string;\n name: string;\n interval: string;\n amount: number;\n currency: string;\n}\n\nexport interface TenantSubscription {\n id: string;\n planId: string;\n customerId: string;\n customerEmail: string;\n status: string;\n amount: number;\n currency: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n nextPaymentDate: string | null;\n cancelledAt: string | null;\n paymentsCount: number;\n createdAt: string;\n plan?: TenantSubscriptionPlan | null;\n customer?: { id: string; name: string | null; email: string } | null;\n}\n\nexport interface TenantSubscriptionStats {\n totalActive: number;\n totalNonRenewing: number;\n totalCancelled: number;\n monthlyRecurringRevenue: number;\n}\n\nexport interface TenantSubscriptionsData {\n subscriptions: TenantSubscription[];\n total: number;\n page: number;\n limit: number;\n stats: TenantSubscriptionStats;\n}\n\nexport interface AdminsAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n admins: number;\n active: number;\n suspended: number;\n superadmins: number;\n standardAdmins: number;\n neverLoggedIn: number;\n activeInRange: number;\n actionsInRange: number;\n };\n roleBreakdown: Array<{ role: string; count: number }>;\n statusBreakdown: Array<{ status: string; count: number }>;\n activitySeries: Array<{ date: string; count: number }>;\n topActions: Array<{ action: string; count: number }>;\n recentActivity: Array<{\n id: string;\n adminEmail: string | null;\n action: string;\n targetType: string | null;\n createdAt: string;\n }>;\n}\n\nexport interface AdminSession {\n id: string;\n email: string;\n name: string | null;\n role: 'admin' | 'superadmin';\n permissions: string[];\n mustChangePassword: boolean;\n}\n\nexport interface AdminLoginCodeRequired {\n codeRequired: true;\n challengeId: string;\n /** The address the code went to, masked: `a***@gmail.com`. */\n sentTo: string;\n}\n\nexport type AdminLoginAnswer =\n | AdminLoginCodeRequired\n | {\n codeRequired?: undefined;\n mustChangePassword: boolean;\n admin: Omit<AdminSession, 'permissions'>;\n };\n\nexport const platformAdminApi = {\n /**\n * Password step. A box that emails sign-in codes answers `codeRequired` and\n * sets no session yet; finish with `verifyLoginCode`.\n */\n login: (email: string, password: string) =>\n apiFetch<AdminLoginAnswer>('/platform-admin/v1/auth/login', {\n method: 'POST',\n body: JSON.stringify({ email, password }),\n }),\n verifyLoginCode: (challengeId: string, code: string) =>\n apiFetch<{\n mustChangePassword: boolean;\n admin: Omit<AdminSession, 'permissions'>;\n }>('/platform-admin/v1/auth/login/verify', {\n method: 'POST',\n body: JSON.stringify({ challengeId, code }),\n }),\n resendLoginCode: (challengeId: string) =>\n apiFetch<AdminLoginCodeRequired>('/platform-admin/v1/auth/login/resend', {\n method: 'POST',\n body: JSON.stringify({ challengeId }),\n }),\n logout: () =>\n apiFetch<{ success: boolean }>('/platform-admin/v1/auth/logout', {\n method: 'POST',\n }),\n me: () => apiFetch<AdminSession>('/platform-admin/v1/auth/me'),\n changePassword: (currentPassword: string, newPassword: string) =>\n apiFetch<{ success: boolean }>('/platform-admin/v1/auth/change-password', {\n method: 'POST',\n body: JSON.stringify({ currentPassword, newPassword }),\n }),\n overview: () => apiFetch<PlatformOverview>('/platform-admin/v1/overview'),\n cockpit: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<PlatformCockpit>(\n `/platform-admin/v1/overview/cockpit${q ? `?${q}` : ''}`,\n );\n },\n revenue: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<PlatformRevenue>(\n `/platform-admin/v1/overview/revenue${q ? `?${q}` : ''}`,\n );\n },\n tenantsAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<TenantsAnalytics>(\n `/platform-admin/v1/overview/tenants-analytics${q ? `?${q}` : ''}`,\n );\n },\n tenants: (params: TenantListParams = {}) =>\n apiFetch<TenantsPage>(`/platform-admin/v1/tenants${tenantsQuery(params)}`),\n tenant: (\n id: string,\n range: { startDate?: string; endDate?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n const query = qs.toString();\n return apiFetch<TenantDetail>(\n `/platform-admin/v1/tenants/${id}${query ? `?${query}` : ''}`,\n );\n },\n tenantAnalytics: (\n id: string,\n range: { startDate?: string; endDate?: string; limit?: number } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n if (range.limit) qs.set('limit', String(range.limit));\n const query = qs.toString();\n return apiFetch<DashboardStats>(\n `/platform-admin/v1/tenants/${id}/analytics${query ? `?${query}` : ''}`,\n );\n },\n tenantFinance: (\n id: string,\n range: { startDate?: string; endDate?: string; period?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n if (range.period) qs.set('period', range.period);\n const query = qs.toString();\n return apiFetch<AdminFinanceAnalytics>(\n `/platform-admin/v1/tenants/${id}/finance${query ? `?${query}` : ''}`,\n );\n },\n tenantTransactions: (\n id: string,\n params: {\n status?: string;\n type?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.type) qs.set('type', params.type);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantTransactionsPage>(\n `/platform-admin/v1/tenants/${id}/transactions${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantCustomers: (\n id: string,\n params: {\n search?: string;\n type?: string;\n status?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.search) qs.set('search', params.search);\n if (params.type) qs.set('type', params.type);\n if (params.status) qs.set('status', params.status);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantCustomersPage>(\n `/platform-admin/v1/tenants/${id}/customers${query ? `?${query}` : ''}`,\n );\n },\n tenantProducts: (\n id: string,\n params: { type?: string; search?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.type) qs.set('type', params.type);\n if (params.search) qs.set('search', params.search);\n const query = qs.toString();\n return apiFetch<TenantProductsData>(\n `/platform-admin/v1/tenants/${id}/products${query ? `?${query}` : ''}`,\n );\n },\n tenantProductInsights: (id: string, range: { startDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n const query = qs.toString();\n return apiFetch<ProductInsights>(\n `/platform-admin/v1/tenants/${id}/products/insights${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantCustomerInsights: (id: string, range: { startDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n const query = qs.toString();\n return apiFetch<CustomerInsights>(\n `/platform-admin/v1/tenants/${id}/customers/insights${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantInvoices: (\n id: string,\n params: {\n status?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantInvoicesData>(\n `/platform-admin/v1/tenants/${id}/invoices${query ? `?${query}` : ''}`,\n );\n },\n tenantLoyalty: (id: string) =>\n apiFetch<TenantLoyaltyData>(`/platform-admin/v1/tenants/${id}/loyalty`),\n tenantDiscounts: (\n id: string,\n params: {\n status?: string;\n discountType?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.discountType) qs.set('discountType', params.discountType);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantDiscountsPage>(\n `/platform-admin/v1/tenants/${id}/discounts${query ? `?${query}` : ''}`,\n );\n },\n tenantSettlements: (\n id: string,\n params: {\n page?: number;\n limit?: number;\n startDate?: string;\n endDate?: string;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const query = qs.toString();\n return apiFetch<TenantSettlementsData>(\n `/platform-admin/v1/tenants/${id}/settlements${query ? `?${query}` : ''}`,\n );\n },\n tenantSubscriptions: (\n id: string,\n params: {\n status?: string;\n planId?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.planId) qs.set('planId', params.planId);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantSubscriptionsData>(\n `/platform-admin/v1/tenants/${id}/subscriptions${\n query ? `?${query}` : ''\n }`,\n );\n },\n setTenantStatus: (id: string, status: TenantStatus) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/tenants/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n accounts: (\n params: {\n page?: number;\n pageSize?: number;\n search?: string;\n joinedFrom?: string;\n joinedTo?: string;\n stage?: AccountStage;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.pageSize) qs.set('pageSize', String(params.pageSize));\n if (params.search) qs.set('search', params.search);\n if (params.joinedFrom) qs.set('joinedFrom', params.joinedFrom);\n if (params.joinedTo) qs.set('joinedTo', params.joinedTo);\n if (params.stage) qs.set('stage', params.stage);\n const query = qs.toString();\n return apiFetch<AccountsPage>(\n `/platform-admin/v1/accounts${query ? `?${query}` : ''}`,\n );\n },\n accountsAnalytics: (\n params: { startDate?: string; endDate?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AccountsAnalytics>(\n `/platform-admin/v1/accounts/analytics${q ? `?${q}` : ''}`,\n );\n },\n setAccountStatus: (id: string, status: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/accounts/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n verifyAccount: (id: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/accounts/${id}/verify`, {\n method: 'POST',\n }),\n accountSessions: (id: string) =>\n apiFetch<AccountSession[]>(`/platform-admin/v1/accounts/${id}/sessions`),\n accountTenants: (id: string) =>\n apiFetch<AccountTenantRow[]>(`/platform-admin/v1/accounts/${id}/tenants`),\n impersonateAccount: (id: string) =>\n apiFetch<{ success: boolean }>(\n `/platform-admin/v1/accounts/${id}/impersonate`,\n { method: 'POST' },\n ),\n admins: () => apiFetch<AdminRow[]>('/platform-admin/v1/admins'),\n adminsAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AdminsAnalytics>(\n `/platform-admin/v1/admins/analytics${q ? `?${q}` : ''}`,\n );\n },\n adminPermissions: () =>\n apiFetch<string[]>('/platform-admin/v1/admins/permissions'),\n inviteAdmin: (\n email: string,\n role: 'admin' | 'superadmin',\n permissions: string[] = [],\n roleIds: string[] = [],\n ) =>\n apiFetch<{ email: string; tempPassword: string }>(\n '/platform-admin/v1/admins',\n {\n method: 'POST',\n body: JSON.stringify({ email, role, permissions, roleIds }),\n },\n ),\n setAdminStatus: (id: string, status: 'active' | 'suspended') =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/admins/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n setAdminPermissions: (id: string, permissions: string[]) =>\n apiFetch<{ success: boolean }>(\n `/platform-admin/v1/admins/${id}/permissions`,\n { method: 'PATCH', body: JSON.stringify({ permissions }) },\n ),\n setAdminRoles: (id: string, roleIds: string[]) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/admins/${id}/roles`, {\n method: 'PATCH',\n body: JSON.stringify({ roleIds }),\n }),\n resetAdminPassword: (id: string) =>\n apiFetch<{ tempPassword: string }>(\n `/platform-admin/v1/admins/${id}/reset-password`,\n { method: 'POST' },\n ),\n roles: () => apiFetch<RoleRow[]>('/platform-admin/v1/roles'),\n createRole: (name: string, permissions: string[], description?: string) =>\n apiFetch<RoleRow>('/platform-admin/v1/roles', {\n method: 'POST',\n body: JSON.stringify({ name, permissions, description }),\n }),\n updateRole: (\n id: string,\n data: { name?: string; permissions?: string[]; description?: string },\n ) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/roles/${id}`, {\n method: 'PATCH',\n body: JSON.stringify(data),\n }),\n deleteRole: (id: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/roles/${id}`, {\n method: 'DELETE',\n }),\n audit: (\n params: {\n page?: number;\n pageSize?: number;\n search?: string;\n action?: string;\n adminEmail?: string;\n from?: string;\n to?: string;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.pageSize) qs.set('pageSize', String(params.pageSize));\n if (params.search) qs.set('search', params.search);\n if (params.action) qs.set('action', params.action);\n if (params.adminEmail) qs.set('adminEmail', params.adminEmail);\n if (params.from) qs.set('from', params.from);\n if (params.to) qs.set('to', params.to);\n const q = qs.toString();\n return apiFetch<AuditPage>(`/platform-admin/v1/audit${q ? `?${q}` : ''}`);\n },\n auditAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AuditAnalytics>(\n `/platform-admin/v1/audit/analytics${q ? `?${q}` : ''}`,\n );\n },\n};\n\nexport interface AdminRow {\n id: string;\n email: string;\n name: string | null;\n role: 'admin' | 'superadmin';\n status: 'active' | 'suspended';\n permissions: string[];\n roleIds: string[];\n mustChangePassword: boolean;\n lastLoginAt: string | null;\n createdAt: string;\n}\n\nexport interface RoleRow {\n id: string;\n key: string;\n name: string;\n description: string | null;\n permissions: string[];\n isSystem: boolean;\n assignedCount: number;\n}\n\nexport interface AuditRow {\n id: string;\n /** Who did it, by name. Absent from an engine that does not send it, or when the admin has none. */\n adminName?: string | null;\n adminEmail: string | null;\n action: string;\n targetType: string | null;\n targetId: string | null;\n metadata: Record<string, unknown>;\n ipAddress: string | null;\n /** The browser or tool the action came from. Absent from an engine that does not send it. */\n userAgent?: string | null;\n createdAt: string;\n}\n\nexport interface AuditPage {\n rows: AuditRow[];\n total: number;\n page: number;\n pageSize: number;\n}\nexport interface AuditAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n actions: number;\n activeAdmins: number;\n actionTypes: number;\n topAction: string | null;\n };\n actionSeries: Array<{ date: string; count: number }>;\n actionBreakdown: Array<{ action: string; count: number }>;\n adminBreakdown: Array<{ adminEmail: string; count: number }>;\n targetBreakdown: Array<{ targetType: string; count: number }>;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/admin-api.ts"],"sourcesContent":["import {\n apiFetch,\n type DashboardStats,\n type FinanceAnalytics,\n type Transaction,\n} from './api';\n\nexport type {\n AccountRow,\n AccountsPage,\n AccountTenantRow,\n AccountSession,\n AccountStage,\n AccountKycStatus,\n TenantTeamMember,\n AccountsAnalytics,\n} from './admin-account-types';\nimport type {\n AccountRow,\n AccountSession,\n AccountStage,\n AccountsPage,\n AccountTenantRow,\n TenantTeamMember,\n AccountsAnalytics,\n} from './admin-account-types';\nimport type { TenantSetup } from './admin-tenant-setup-types';\nimport type { CountryFields } from './admin-country-api';\nimport { tenantsQuery, type TenantListParams } from './admin-tenants-query';\nimport type { AccountOfficer } from './admin-account-officer-api';\nimport type {\n CurrencyAmount,\n CurrencyGmvKpi,\n CurrencyOverdue,\n CurrencyPerformance,\n CurrencyRevenueGmv,\n CurrencyRevenueQuality,\n CurrencySeries,\n CurrencySettlementSummary,\n CurrencyTopTenants,\n CurrencyTotals,\n FinanceByCurrency,\n TenantCurrencyMetrics,\n} from './admin-currency-types';\nexport type * from './admin-currency-types';\n\nexport type { DashboardStats, FinanceAnalytics, Transaction } from './api';\n\n/** A merchant's finance dashboard as the admin API sends it: per currency too. */\nexport type AdminFinanceAnalytics = FinanceAnalytics & FinanceByCurrency;\n\nexport interface TenantTransactionsPage {\n transactions: Transaction[];\n pagination: {\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n };\n}\n\n// ============================================\n// PLATFORM ADMIN API (growth cockpit)\n// Cross-tenant aggregates — admin/superadmin only.\n// ============================================\n\nexport interface PlatformOverview {\n tenants: { total: number; active: number; new30d: number; new7d: number };\n accounts: { total: number; new30d: number };\n orders: { total: number; gmv: number; gmv30d: number };\n subscriptions: { active: number; trialing: number };\n growth: { tenantSeries: Array<{ date: string; count: number }> };\n}\n\nexport interface TenantsAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n tenants: number;\n accounts: number;\n avgTenantsPerAccount: number;\n activeRate: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvInRange: number;\n ordersInRange: number;\n newTenantsInRange: number;\n };\n statusBreakdown: Array<{ status: string; count: number }>;\n industryBreakdown: Array<{ industry: string; count: number }>;\n onboardingSeries: Array<{ date: string; count: number }>;\n performanceSeries: Array<{ date: string; gmv: number; orders: number }>;\n /** Absent until the matching api deploy lands — guard with `?? []`. */\n previousOnboardingSeries?: Array<{ date: string; count: number }>;\n previousPerformanceSeries?: Array<{\n date: string;\n gmv: number;\n orders: number;\n }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n /** @deprecated adds currencies together, not converted. */\n baseCurrency: string;\n /** @deprecated never convert with these. */\n rates: Record<string, number>;\n currencies?: string[];\n totalsByCurrency?: CurrencyTotals[];\n performanceSeriesByCurrency?: CurrencySeries[];\n topTenantsByCurrency?: CurrencyTopTenants[];\n}\n\nexport interface CockpitKpi {\n current: number;\n previous: number;\n pct: number | null;\n}\n\ninterface AttentionTenantRef {\n id: string;\n businessName: string;\n slug: string;\n}\n\nexport interface PlatformCockpit {\n range: { startDate: string; endDate: string };\n // Base currency all monetary figures are expressed in (USD). `rates` maps a\n // currency code to its rate-to-USD, so the client can render figures in a\n // chosen display currency by dividing a USD amount by the target's rate.\n baseCurrency: string;\n rates: Record<string, number>;\n /** Currencies with money in this payload, A→Z. */\n currencies?: string[];\n topTenantsByCurrency?: CurrencyTopTenants[];\n kpis: {\n newTenants: CockpitKpi;\n newAccounts: CockpitKpi;\n /** @deprecated adds currencies together; use `gmvByCurrency`. */\n gmv: CockpitKpi;\n orders: CockpitKpi;\n gmvByCurrency?: CurrencyGmvKpi[];\n };\n totals: {\n totalTenants: number;\n activeTenants: number;\n totalAccounts: number;\n activeSubscriptions: number;\n trialingSubscriptions: number;\n /** @deprecated adds currencies together; use `lifetimeGmvByCurrency`. */\n lifetimeGmv: number;\n lifetimeGmvByCurrency?: CurrencyAmount[];\n /**\n * Platform fees collected on card payments, one row per currency. Absent\n * until the api serves it; the Overview shows no card without it.\n */\n gatewayFeesByCurrency?: CurrencyAmount[];\n /**\n * Wallets whose business passed KYC / KYB. Absent until the api serves\n * it; the Overview shows no card without it.\n */\n verifiedWallets?: number;\n };\n sparklines: {\n tenants: number[];\n accounts: number[];\n gmv: number[];\n orders: number[];\n };\n statusBreakdown: Array<{ status: string; count: number }>;\n industryBreakdown: Array<{ industry: string; count: number }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n health?: {\n mrr: number;\n newMrr: number;\n churnedMrr: number;\n netNewMrr: number;\n grossMrrChurnPct: number;\n grossRevenueRetentionPct: number;\n newLogos: number;\n churnedLogos: number;\n netNewLogos: number;\n logoChurnPct: number;\n activePayingLogos: number;\n gmvConcentrationTop10Pct: number;\n };\n performance?: {\n takeRatePct: number | null;\n annualizedGmvRunRate: number;\n gmvPerActiveTenant: number;\n revenuePerActiveTenant: number;\n transactingTenants: number;\n transactingTenantRatePct: number;\n gmvGrowthPct: number | null;\n ordersGrowthPct: number | null;\n netNewLogos: number;\n byCurrency?: CurrencyPerformance[];\n };\n verticals?: Array<{\n industry: string;\n tenants: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvGrowthPct: number | null;\n share: number;\n }>;\n /** GMV/orders across every service Box offers (sell-products, event-tickets, …). */\n salesByService?: Array<{\n service: string;\n merchants: number;\n gmv: number;\n orders: number;\n aov: number;\n gmvGrowthPct: number | null;\n share: number;\n }>;\n activation?: {\n funnel: Array<{ stage: string; count: number }>;\n medianDaysToFirstOrder: number | null;\n activationRatePct: number;\n orderConversionPct: number;\n };\n accounts?: {\n total: number;\n active: number;\n suspended: number;\n verified: number;\n unverifiedEmail: number;\n neverLoggedIn: number;\n dormant: number;\n new: number;\n };\n trend: {\n performanceSeries: Array<{ date: string; gmv: number; orders: number }>;\n onboardingSeries: Array<{ date: string; count: number }>;\n /** Absent until the matching api deploy lands — guard with `?? []`. */\n previousPerformanceSeries?: Array<{\n date: string;\n gmv: number;\n orders: number;\n }>;\n previousOnboardingSeries?: Array<{ date: string; count: number }>;\n performanceSeriesByCurrency?: CurrencySeries[];\n };\n attention: {\n /**\n * Feeds whose query failed; their counts are placeholders, not zeros.\n * Absent when talking to an API that predates this field.\n */\n unavailable?: Array<\n 'needsReview' | 'dormantTenants' | 'overdueInvoices' | 'failedSettlements'\n >;\n trialsEndingSoon: Array<\n AttentionTenantRef & { trialEndsAt: string; daysLeft: number }\n >;\n needsReview: Array<\n AttentionTenantRef & { status: string; createdAt: string }\n >;\n dormantTenants: Array<AttentionTenantRef & { createdAt: string }>;\n overdueInvoices: {\n count: number;\n /** @deprecated adds currencies together; use `totalByCurrency`. */\n total: number;\n totalByCurrency?: CurrencyOverdue[];\n sample: Array<{\n id: string;\n invoiceNumber: string;\n tenantId: string;\n tenantName: string;\n customerName: string | null;\n amountDue: number;\n currency: string;\n dueDate: string | null;\n }>;\n };\n failedSettlements: {\n count: number;\n sample: Array<{\n id: string;\n tenantId: string;\n tenantName: string;\n netAmount: number;\n currency: string;\n createdAt: string;\n }>;\n };\n };\n}\n\n/**\n * What one payment channel (Card, USSD, Bank transfer, Opay...) brought in, in one\n * currency. `amountMinor` is in minor units. Sent only by a box that records how\n * customers paid; others answer 404, and the panels that use it stay hidden.\n */\nexport interface GatewayChannelTotal {\n channel: { key: string; label: string };\n currency: string;\n count: number;\n amountMinor: string;\n}\n\nexport interface PlatformRevenue {\n range: { startDate: string; endDate: string };\n currency: string;\n /**\n * What Olive keeps from payouts, settlements and subscription charges: net\n * credits on the ledger's platform fees account, in major units, one row per\n * currency, A to Z. Empty when nothing was earned. Not card fees only, no\n * refund netting, and test merchants are included. Absent until the api\n * serves it, so the UI hides the figure rather than showing a zero.\n */\n platformFeesEarnedByCurrency?: CurrencyAmount[];\n recurring: {\n /** False when no billing source feeds the figures below (all are 0). */\n tracked?: boolean;\n mrr: number;\n arr: number;\n arpa: number;\n activeSubscriptions: number;\n trialingSubscriptions: number;\n pastDueSubscriptions: number;\n nonRenewingSubscriptions: number;\n cancelledSubscriptions: number;\n newInRange: number;\n churnedInRange: number;\n planBreakdown: Array<{\n planId: string;\n name: string;\n interval: string;\n subscribers: number;\n mrr: number;\n }>;\n };\n gmv: {\n lifetime: number;\n inRange: number;\n ordersInRange: number;\n aov: number;\n series: Array<{ date: string; gmv: number; orders: number }>;\n topTenants: Array<{\n id: string;\n businessName: string;\n slug: string;\n gmv: number;\n orders: number;\n }>;\n };\n quality?: {\n quickRatio: number | null;\n nrrPct: number | null;\n expansionMrr: number;\n contractionMrr: number;\n mrrChurnRatePct: number | null;\n logoChurnRatePct: number | null;\n grossGmv: number;\n refundedGmv: number;\n netGmv: number;\n refundRatePct: number;\n refundedOrders: number;\n cohorts: Array<{\n cohort: string;\n size: number;\n retention: Array<number | null>;\n }>;\n gmvByCurrency?: CurrencyRevenueQuality[];\n };\n /** @deprecated never convert with these. */\n rates: Record<string, number>;\n currencies?: string[];\n gmvByCurrency?: CurrencyRevenueGmv[];\n}\n\nexport type TenantStatus = 'active' | 'suspended' | 'pending' | 'deleted';\n\nexport interface TenantRow extends CountryFields {\n id: string;\n slug: string;\n businessName: string;\n status: TenantStatus;\n industryKey: string | null;\n createdAt: string;\n /** The business's contact email (absent on older APIs). */\n email?: string | null;\n phone?: string | null;\n /** The owner's sign-in email. */\n ownerEmail?: string | null;\n /** @deprecated adds currencies together; use `gmvByCurrency`. */\n gmv: number;\n gmvByCurrency?: CurrencyAmount[];\n /** The merchant's account officer (absent on older APIs). */\n accountOfficer?: Pick<AccountOfficer, 'id' | 'name'> | null;\n}\n\nexport interface TenantsPage {\n rows: TenantRow[];\n total: number;\n page: number;\n pageSize: number;\n}\n\nexport interface TenantActivityOrder {\n id: string;\n orderNumber: string;\n total: number;\n currency: string;\n status: string;\n paymentStatus: string;\n customerEmail: string;\n customerName: string | null;\n createdAt: string;\n}\n\nexport interface TenantDetail extends TenantSetup {\n /** Who runs the workspace and how to reach it (absent on older APIs). */\n contact?: { email: string | null; phone: string | null };\n owner?: TenantTeamMember | null;\n team?: TenantTeamMember[];\n /** The admin in charge of this merchant (absent on older APIs). */\n accountOfficer?: AccountOfficer | null;\n id: string;\n slug: string;\n businessName: string;\n status: TenantStatus;\n industryKey: string | null;\n customDomain: string | null;\n createdAt: string;\n chargeBearer: 'merchant' | 'customer';\n currency: string;\n metrics: {\n totalOrders: number;\n paidOrders: number;\n pendingOrders: number;\n gmv: number;\n gmv30d: number;\n gmv7d: number;\n aov: number;\n totalCustomers: number;\n subscriptionStatus: string | null;\n window: {\n startDate: string;\n endDate: string;\n gmv: number;\n orders: number;\n paidOrders: number;\n aov: number;\n customers: number;\n };\n byCurrency?: TenantCurrencyMetrics[];\n };\n /** Currencies with paid orders, A→Z. */\n currencies?: string[];\n revenueSeries: Array<{ date: string; amount: number }>;\n revenueSeriesByCurrency?: Array<{\n currency: string;\n series: Array<{ date: string; amount: number }>;\n }>;\n recentOrders: TenantActivityOrder[];\n}\n\n// ---- Iteration 3: tenant cockpit domains ----\n\nexport interface TenantCustomer {\n id: string;\n email: string;\n phone: string | null;\n name: string | null;\n type: string;\n source: string | null;\n status: string;\n emailVerified: boolean;\n totalOrders: number;\n totalSpent: number;\n lastOrderAt: string | null;\n createdAt: string;\n}\n\nexport interface TenantCustomersPage {\n members: TenantCustomer[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\nexport interface TenantProduct {\n id: string;\n type: string;\n slug: string;\n title: string;\n category: string | null;\n tags: string[];\n featured: boolean;\n isActive: boolean;\n image?: { url: string } | null;\n price: number | null;\n compareAtPrice: number | null;\n currency: string | null;\n trackInventory: boolean;\n quantity: number | null;\n reserved: number | null;\n lowStockThreshold: number | null;\n createdAt: string;\n}\n\nexport interface TenantProductStats {\n total: number;\n active: number;\n featured: number;\n lowStock: number;\n outOfStock: number;\n}\n\nexport interface TenantProductsData {\n items: TenantProduct[];\n total: number;\n stats: TenantProductStats;\n}\n\nexport interface ProductRef {\n id: string;\n title: string;\n}\n\nexport interface SellerRow {\n id: string;\n title: string;\n units: number;\n revenue: number;\n}\n\nexport interface CategorySlice {\n category: string;\n count: number;\n value: number;\n}\n\nexport interface ProductInsights {\n currency: string;\n totalProducts: number;\n activeProducts: number;\n featuredProducts: number;\n lowStock: number;\n outOfStock: number;\n trackedProducts: number;\n catalogValue: number;\n inventoryValue: number;\n inventoryAtRiskValue: number;\n avgPrice: number;\n medianPrice: number;\n totalUnitsSold: number;\n totalRevenue: number;\n pctEverSold: number;\n deadStock: number;\n newestProduct: (ProductRef & { createdAt: string }) | null;\n lastUpdatedProduct: (ProductRef & { updatedAt: string }) | null;\n categories: CategorySlice[];\n bestSellers: SellerRow[];\n worstSellers: SellerRow[];\n featuredSellThrough: {\n featuredTotal: number;\n featuredSold: number;\n featuredUnits: number;\n nonFeaturedTotal: number;\n nonFeaturedSold: number;\n nonFeaturedUnits: number;\n };\n unitsSeries: Array<{ date: string; count: number }>;\n}\n\nexport interface SpenderRow {\n id: string;\n name: string | null;\n email: string;\n totalSpent: number;\n totalOrders: number;\n}\n\nexport interface BreakdownSlice {\n label: string;\n count: number;\n}\n\nexport interface CustomerInsights {\n currency: string;\n totalCustomers: number;\n newCustomers30d: number;\n payingCustomers: number;\n repeatCustomers: number;\n repeatRate: number;\n dormantCustomers: number;\n marketingOptInRate: number;\n lifetimeValue: number;\n avgSpendPerCustomer: number;\n avgOrdersPerCustomer: number;\n avgOrderValue: number;\n topSpenders: SpenderRow[];\n bySource: BreakdownSlice[];\n byType: BreakdownSlice[];\n signupsSeries: Array<{ date: string; count: number }>;\n}\n\nexport interface TenantInvoice {\n id: string;\n invoiceNumber: string;\n status: string;\n customerEmail: string | null;\n customerName: string | null;\n total: number;\n amountPaid: number;\n amountDue: number;\n currency: string;\n dueDate: string | null;\n createdAt: string;\n}\n\nexport interface TenantInvoiceStats {\n draft: number;\n sent: number;\n paid: number;\n overdue: number;\n cancelled: number;\n total: number;\n totalRevenue: number;\n totalOutstanding: number;\n}\n\nexport interface TenantInvoicesData {\n invoices: TenantInvoice[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n stats: TenantInvoiceStats;\n}\n\nexport interface TenantLoyaltyProgram {\n id: string;\n name: string;\n pointsName: string;\n pointsPerCurrency: number;\n currencyPerPoint: number;\n isActive: boolean;\n tiers?: Array<{ id: string; name: string; threshold: number }>;\n earnRules?: Array<{ id: string; name: string; points: number }>;\n}\n\nexport interface TenantLoyaltyStats {\n totalMembers: number;\n totalPointsIssued: number;\n totalPointsRedeemed: number;\n activeMembers: number;\n programActive: boolean;\n}\n\nexport interface TenantLoyaltyData {\n program: TenantLoyaltyProgram | null;\n stats: TenantLoyaltyStats;\n}\n\nexport interface TenantDiscount {\n id: string;\n name: string;\n code: string;\n discountType: string;\n value: number;\n maxDiscountAmount: number | null;\n startsAt: string | null;\n endsAt: string | null;\n usageLimit: number | null;\n usageCount: number;\n status: string;\n autoApply: boolean;\n isValid: boolean;\n isExpired: boolean;\n createdAt: string;\n}\n\nexport interface TenantDiscountsPage {\n discounts: TenantDiscount[];\n total: number;\n page: number;\n limit: number;\n totalPages: number;\n}\n\nexport interface TenantSettlement {\n id: string;\n grossAmount: number;\n paystackFee: number;\n platformFee: number;\n netAmount: number;\n currency: string;\n status: string;\n settlementType: string;\n bankAccount?: { bankName: string; accountNumber: string } | null;\n settledAt: string | null;\n createdAt: string;\n}\n\nexport interface TenantSettlementSummary {\n totalSettled: number;\n totalPending: number;\n totalFailed: number;\n count: number;\n platformFeesCollected: number;\n currency: string;\n currencies?: string[];\n byCurrency?: CurrencySettlementSummary[];\n}\n\nexport interface TenantBankAccount {\n id: string;\n bankCode: string;\n bankName: string;\n accountNumber: string;\n accountName: string;\n splitPercentage: number | null;\n status: string;\n isDefault: boolean;\n /** Paystack subaccount code (ACCT_…). */\n subaccountCode?: string | null;\n failureReason?: string | null;\n createdAt: string;\n}\n\nexport interface TenantSettlementsData {\n settlements: TenantSettlement[];\n total: number;\n page: number;\n limit: number;\n summary: TenantSettlementSummary;\n bankAccounts: TenantBankAccount[];\n}\n\nexport interface TenantSubscriptionPlan {\n id: string;\n name: string;\n interval: string;\n amount: number;\n currency: string;\n}\n\nexport interface TenantSubscription {\n id: string;\n planId: string;\n customerId: string;\n customerEmail: string;\n status: string;\n amount: number;\n currency: string;\n currentPeriodStart: string | null;\n currentPeriodEnd: string | null;\n nextPaymentDate: string | null;\n cancelledAt: string | null;\n paymentsCount: number;\n createdAt: string;\n plan?: TenantSubscriptionPlan | null;\n customer?: { id: string; name: string | null; email: string } | null;\n}\n\nexport interface TenantSubscriptionStats {\n totalActive: number;\n totalNonRenewing: number;\n totalCancelled: number;\n monthlyRecurringRevenue: number;\n}\n\nexport interface TenantSubscriptionsData {\n subscriptions: TenantSubscription[];\n total: number;\n page: number;\n limit: number;\n stats: TenantSubscriptionStats;\n}\n\nexport interface AdminsAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n admins: number;\n active: number;\n suspended: number;\n superadmins: number;\n standardAdmins: number;\n neverLoggedIn: number;\n activeInRange: number;\n actionsInRange: number;\n };\n roleBreakdown: Array<{ role: string; count: number }>;\n statusBreakdown: Array<{ status: string; count: number }>;\n activitySeries: Array<{ date: string; count: number }>;\n topActions: Array<{ action: string; count: number }>;\n recentActivity: Array<{\n id: string;\n adminEmail: string | null;\n action: string;\n targetType: string | null;\n createdAt: string;\n }>;\n}\n\nexport interface AdminSession {\n id: string;\n email: string;\n name: string | null;\n role: 'admin' | 'superadmin';\n permissions: string[];\n mustChangePassword: boolean;\n}\n\nexport interface AdminLoginCodeRequired {\n codeRequired: true;\n challengeId: string;\n /** The address the code went to, masked: `a***@gmail.com`. */\n sentTo: string;\n}\n\nexport type AdminLoginAnswer =\n | AdminLoginCodeRequired\n | {\n codeRequired?: undefined;\n mustChangePassword: boolean;\n admin: Omit<AdminSession, 'permissions'>;\n };\n\nexport const platformAdminApi = {\n /**\n * Password step. A box that emails sign-in codes answers `codeRequired` and\n * sets no session yet; finish with `verifyLoginCode`.\n */\n login: (email: string, password: string) =>\n apiFetch<AdminLoginAnswer>('/platform-admin/v1/auth/login', {\n method: 'POST',\n body: JSON.stringify({ email, password }),\n }),\n verifyLoginCode: (challengeId: string, code: string) =>\n apiFetch<{\n mustChangePassword: boolean;\n admin: Omit<AdminSession, 'permissions'>;\n }>('/platform-admin/v1/auth/login/verify', {\n method: 'POST',\n body: JSON.stringify({ challengeId, code }),\n }),\n resendLoginCode: (challengeId: string) =>\n apiFetch<AdminLoginCodeRequired>('/platform-admin/v1/auth/login/resend', {\n method: 'POST',\n body: JSON.stringify({ challengeId }),\n }),\n logout: () =>\n apiFetch<{ success: boolean }>('/platform-admin/v1/auth/logout', {\n method: 'POST',\n }),\n me: () => apiFetch<AdminSession>('/platform-admin/v1/auth/me'),\n changePassword: (currentPassword: string, newPassword: string) =>\n apiFetch<{ success: boolean }>('/platform-admin/v1/auth/change-password', {\n method: 'POST',\n body: JSON.stringify({ currentPassword, newPassword }),\n }),\n overview: () => apiFetch<PlatformOverview>('/platform-admin/v1/overview'),\n gatewayChannels: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<{ byChannel: GatewayChannelTotal[] }>(\n `/platform-admin/v1/gateway-payments/channels${q ? `?${q}` : ''}`,\n );\n },\n cockpit: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<PlatformCockpit>(\n `/platform-admin/v1/overview/cockpit${q ? `?${q}` : ''}`,\n );\n },\n revenue: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<PlatformRevenue>(\n `/platform-admin/v1/overview/revenue${q ? `?${q}` : ''}`,\n );\n },\n tenantsAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<TenantsAnalytics>(\n `/platform-admin/v1/overview/tenants-analytics${q ? `?${q}` : ''}`,\n );\n },\n tenants: (params: TenantListParams = {}) =>\n apiFetch<TenantsPage>(`/platform-admin/v1/tenants${tenantsQuery(params)}`),\n tenant: (\n id: string,\n range: { startDate?: string; endDate?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n const query = qs.toString();\n return apiFetch<TenantDetail>(\n `/platform-admin/v1/tenants/${id}${query ? `?${query}` : ''}`,\n );\n },\n tenantAnalytics: (\n id: string,\n range: { startDate?: string; endDate?: string; limit?: number } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n if (range.limit) qs.set('limit', String(range.limit));\n const query = qs.toString();\n return apiFetch<DashboardStats>(\n `/platform-admin/v1/tenants/${id}/analytics${query ? `?${query}` : ''}`,\n );\n },\n tenantFinance: (\n id: string,\n range: { startDate?: string; endDate?: string; period?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n if (range.endDate) qs.set('endDate', range.endDate);\n if (range.period) qs.set('period', range.period);\n const query = qs.toString();\n return apiFetch<AdminFinanceAnalytics>(\n `/platform-admin/v1/tenants/${id}/finance${query ? `?${query}` : ''}`,\n );\n },\n tenantTransactions: (\n id: string,\n params: {\n status?: string;\n type?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.type) qs.set('type', params.type);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantTransactionsPage>(\n `/platform-admin/v1/tenants/${id}/transactions${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantCustomers: (\n id: string,\n params: {\n search?: string;\n type?: string;\n status?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.search) qs.set('search', params.search);\n if (params.type) qs.set('type', params.type);\n if (params.status) qs.set('status', params.status);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantCustomersPage>(\n `/platform-admin/v1/tenants/${id}/customers${query ? `?${query}` : ''}`,\n );\n },\n tenantProducts: (\n id: string,\n params: { type?: string; search?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.type) qs.set('type', params.type);\n if (params.search) qs.set('search', params.search);\n const query = qs.toString();\n return apiFetch<TenantProductsData>(\n `/platform-admin/v1/tenants/${id}/products${query ? `?${query}` : ''}`,\n );\n },\n tenantProductInsights: (id: string, range: { startDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n const query = qs.toString();\n return apiFetch<ProductInsights>(\n `/platform-admin/v1/tenants/${id}/products/insights${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantCustomerInsights: (id: string, range: { startDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (range.startDate) qs.set('startDate', range.startDate);\n const query = qs.toString();\n return apiFetch<CustomerInsights>(\n `/platform-admin/v1/tenants/${id}/customers/insights${\n query ? `?${query}` : ''\n }`,\n );\n },\n tenantInvoices: (\n id: string,\n params: {\n status?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantInvoicesData>(\n `/platform-admin/v1/tenants/${id}/invoices${query ? `?${query}` : ''}`,\n );\n },\n tenantLoyalty: (id: string) =>\n apiFetch<TenantLoyaltyData>(`/platform-admin/v1/tenants/${id}/loyalty`),\n tenantDiscounts: (\n id: string,\n params: {\n status?: string;\n discountType?: string;\n search?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.discountType) qs.set('discountType', params.discountType);\n if (params.search) qs.set('search', params.search);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantDiscountsPage>(\n `/platform-admin/v1/tenants/${id}/discounts${query ? `?${query}` : ''}`,\n );\n },\n tenantSettlements: (\n id: string,\n params: {\n page?: number;\n limit?: number;\n startDate?: string;\n endDate?: string;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const query = qs.toString();\n return apiFetch<TenantSettlementsData>(\n `/platform-admin/v1/tenants/${id}/settlements${query ? `?${query}` : ''}`,\n );\n },\n tenantSubscriptions: (\n id: string,\n params: {\n status?: string;\n planId?: string;\n page?: number;\n limit?: number;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.status) qs.set('status', params.status);\n if (params.planId) qs.set('planId', params.planId);\n if (params.page) qs.set('page', String(params.page));\n if (params.limit) qs.set('limit', String(params.limit));\n const query = qs.toString();\n return apiFetch<TenantSubscriptionsData>(\n `/platform-admin/v1/tenants/${id}/subscriptions${\n query ? `?${query}` : ''\n }`,\n );\n },\n setTenantStatus: (id: string, status: TenantStatus) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/tenants/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n accounts: (\n params: {\n page?: number;\n pageSize?: number;\n search?: string;\n joinedFrom?: string;\n joinedTo?: string;\n stage?: AccountStage;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.pageSize) qs.set('pageSize', String(params.pageSize));\n if (params.search) qs.set('search', params.search);\n if (params.joinedFrom) qs.set('joinedFrom', params.joinedFrom);\n if (params.joinedTo) qs.set('joinedTo', params.joinedTo);\n if (params.stage) qs.set('stage', params.stage);\n const query = qs.toString();\n return apiFetch<AccountsPage>(\n `/platform-admin/v1/accounts${query ? `?${query}` : ''}`,\n );\n },\n accountsAnalytics: (\n params: { startDate?: string; endDate?: string } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AccountsAnalytics>(\n `/platform-admin/v1/accounts/analytics${q ? `?${q}` : ''}`,\n );\n },\n setAccountStatus: (id: string, status: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/accounts/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n verifyAccount: (id: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/accounts/${id}/verify`, {\n method: 'POST',\n }),\n accountSessions: (id: string) =>\n apiFetch<AccountSession[]>(`/platform-admin/v1/accounts/${id}/sessions`),\n accountTenants: (id: string) =>\n apiFetch<AccountTenantRow[]>(`/platform-admin/v1/accounts/${id}/tenants`),\n impersonateAccount: (id: string) =>\n apiFetch<{ success: boolean }>(\n `/platform-admin/v1/accounts/${id}/impersonate`,\n { method: 'POST' },\n ),\n admins: () => apiFetch<AdminRow[]>('/platform-admin/v1/admins'),\n adminsAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AdminsAnalytics>(\n `/platform-admin/v1/admins/analytics${q ? `?${q}` : ''}`,\n );\n },\n adminPermissions: () =>\n apiFetch<string[]>('/platform-admin/v1/admins/permissions'),\n inviteAdmin: (\n email: string,\n role: 'admin' | 'superadmin',\n permissions: string[] = [],\n roleIds: string[] = [],\n ) =>\n apiFetch<{ email: string; tempPassword: string }>(\n '/platform-admin/v1/admins',\n {\n method: 'POST',\n body: JSON.stringify({ email, role, permissions, roleIds }),\n },\n ),\n setAdminStatus: (id: string, status: 'active' | 'suspended') =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/admins/${id}/status`, {\n method: 'PATCH',\n body: JSON.stringify({ status }),\n }),\n setAdminPermissions: (id: string, permissions: string[]) =>\n apiFetch<{ success: boolean }>(\n `/platform-admin/v1/admins/${id}/permissions`,\n { method: 'PATCH', body: JSON.stringify({ permissions }) },\n ),\n setAdminRoles: (id: string, roleIds: string[]) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/admins/${id}/roles`, {\n method: 'PATCH',\n body: JSON.stringify({ roleIds }),\n }),\n resetAdminPassword: (id: string) =>\n apiFetch<{ tempPassword: string }>(\n `/platform-admin/v1/admins/${id}/reset-password`,\n { method: 'POST' },\n ),\n roles: () => apiFetch<RoleRow[]>('/platform-admin/v1/roles'),\n createRole: (name: string, permissions: string[], description?: string) =>\n apiFetch<RoleRow>('/platform-admin/v1/roles', {\n method: 'POST',\n body: JSON.stringify({ name, permissions, description }),\n }),\n updateRole: (\n id: string,\n data: { name?: string; permissions?: string[]; description?: string },\n ) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/roles/${id}`, {\n method: 'PATCH',\n body: JSON.stringify(data),\n }),\n deleteRole: (id: string) =>\n apiFetch<{ success: boolean }>(`/platform-admin/v1/roles/${id}`, {\n method: 'DELETE',\n }),\n audit: (\n params: {\n page?: number;\n pageSize?: number;\n search?: string;\n action?: string;\n adminEmail?: string;\n from?: string;\n to?: string;\n } = {},\n ) => {\n const qs = new URLSearchParams();\n if (params.page) qs.set('page', String(params.page));\n if (params.pageSize) qs.set('pageSize', String(params.pageSize));\n if (params.search) qs.set('search', params.search);\n if (params.action) qs.set('action', params.action);\n if (params.adminEmail) qs.set('adminEmail', params.adminEmail);\n if (params.from) qs.set('from', params.from);\n if (params.to) qs.set('to', params.to);\n const q = qs.toString();\n return apiFetch<AuditPage>(`/platform-admin/v1/audit${q ? `?${q}` : ''}`);\n },\n auditAnalytics: (params: { startDate?: string; endDate?: string } = {}) => {\n const qs = new URLSearchParams();\n if (params.startDate) qs.set('startDate', params.startDate);\n if (params.endDate) qs.set('endDate', params.endDate);\n const q = qs.toString();\n return apiFetch<AuditAnalytics>(\n `/platform-admin/v1/audit/analytics${q ? `?${q}` : ''}`,\n );\n },\n};\n\nexport interface AdminRow {\n id: string;\n email: string;\n name: string | null;\n role: 'admin' | 'superadmin';\n status: 'active' | 'suspended';\n permissions: string[];\n roleIds: string[];\n mustChangePassword: boolean;\n lastLoginAt: string | null;\n createdAt: string;\n}\n\nexport interface RoleRow {\n id: string;\n key: string;\n name: string;\n description: string | null;\n permissions: string[];\n isSystem: boolean;\n assignedCount: number;\n}\n\nexport interface AuditRow {\n id: string;\n /** Who did it, by name. Absent from an engine that does not send it, or when the admin has none. */\n adminName?: string | null;\n adminEmail: string | null;\n action: string;\n targetType: string | null;\n targetId: string | null;\n metadata: Record<string, unknown>;\n ipAddress: string | null;\n /** The browser or tool the action came from. Absent from an engine that does not send it. */\n userAgent?: string | null;\n createdAt: string;\n}\n\nexport interface AuditPage {\n rows: AuditRow[];\n total: number;\n page: number;\n pageSize: number;\n}\nexport interface AuditAnalytics {\n range: { startDate: string; endDate: string };\n totals: {\n actions: number;\n activeAdmins: number;\n actionTypes: number;\n topAction: string | null;\n };\n actionSeries: Array<{ date: string; count: number }>;\n actionBreakdown: Array<{ action: string; count: number }>;\n adminBreakdown: Array<{ adminEmail: string; count: number }>;\n targetBreakdown: Array<{ targetType: string; count: number }>;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withpotter/lib",
3
- "version": "0.13.0-next.89",
3
+ "version": "0.13.0-next.91",
4
4
  "description": "Box dashboard foundation: API client, contexts, types, intent config, and utilities.",
5
5
  "license": "UNLICENSED",
6
6
  "sideEffects": false,