@burdenoff/microfe-devportal 2026.623.8 → 2026.623.9

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.
@@ -1,7 +1,7 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
2
  import { cn as t } from "../utils/cn.js";
3
3
  import { EmptyState as n } from "../components/EmptyState.js";
4
- import { useGetMyOrganizationsQuery as ee, useGetRevenueDashboardDataQuery as te, useLinkDevOrgBillingAccountMutation as ne, useMyBillingAccountsQuery as r } from "../../generated/global-operations.js";
4
+ import { useGetBillingAccountsByOrgQuery as ee, useGetMyOrganizationsQuery as te, useGetRevenueDashboardDataQuery as ne, useLinkDevOrgBillingAccountMutation as r } from "../../generated/global-operations.js";
5
5
  import { getErrorMessage as i } from "../hooks/useGraphQL.js";
6
6
  import { PageLayout as a, PageSection as o } from "../components/PageLayout.js";
7
7
  import { StatCard as s, StatCardGrid as re } from "../components/StatCard.js";
@@ -15,9 +15,9 @@ import { CartesianGrid as f } from "../../node_modules/.bun/recharts@2.15.4_21cc
15
15
  import { Line as p } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/cartesian/Line.js";
16
16
  import { XAxis as m } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/cartesian/XAxis.js";
17
17
  import { YAxis as h } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/cartesian/YAxis.js";
18
- import { LineChart as ae } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/chart/LineChart.js";
19
- import { BarChart as g } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/chart/BarChart.js";
20
- import { useTr as _ } from "../utils/i18n.js";
18
+ import { LineChart as g } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/chart/LineChart.js";
19
+ import { BarChart as _ } from "../../node_modules/.bun/recharts@2.15.4_21ccd8898788a04d/node_modules/recharts/es6/chart/BarChart.js";
20
+ import { useTr as ae } from "../utils/i18n.js";
21
21
  import { useMemo as v, useState as y } from "react";
22
22
  import { AlertCircle as b, ArrowDownToLine as oe, Building2 as x, Check as S, CreditCard as C, DollarSign as w, Link2 as T, Loader2 as E, Wallet as se } from "lucide-react";
23
23
  import { useSearchParams as ce } from "react-router-dom";
@@ -32,14 +32,17 @@ var k = {
32
32
  "90d": 90,
33
33
  "12m": 365
34
34
  }, A = () => {
35
- let A = _(), { activeOrgId: j } = e(), [M, de] = y("90d"), [N, P] = y(!1), [F, I] = y(null), [fe] = ne(), [L, R] = y(!1), [z, B] = y(null), [pe] = ce(), V = v(() => /* @__PURE__ */ new Date(), []), { data: me, loading: H } = r({ fetchPolicy: "cache-and-network" }), he = v(() => {
35
+ let A = ae(), { activeOrgId: j, tenantId: de } = e(), [M, fe] = y("90d"), [N, P] = y(!1), [F, I] = y(null), [pe] = r(), [L, R] = y(!1), [z, B] = y(null), [me] = ce(), V = v(() => /* @__PURE__ */ new Date(), []), { data: he, loading: H } = ee({
36
+ fetchPolicy: "cache-and-network",
37
+ context: { headers: { "x-org-id": de ?? "" } }
38
+ }), ge = v(() => {
36
39
  let e = new Date(V);
37
40
  return e.setDate(e.getDate() - ue[M]), e.toISOString();
38
- }, [V, M]), { data: U, loading: ge, error: W } = ee({ fetchPolicy: "cache-and-network" }), { data: G, loading: _e, error: K } = te({
41
+ }, [V, M]), { data: U, loading: _e, error: W } = te({ fetchPolicy: "cache-and-network" }), { data: G, loading: ve, error: K } = ne({
39
42
  variables: {
40
43
  organizationId: j ?? "",
41
44
  period: "monthly",
42
- startDate: he,
45
+ startDate: ge,
43
46
  endDate: V.toISOString(),
44
47
  salesLimit: 10,
45
48
  salesOffset: 0,
@@ -48,13 +51,13 @@ var k = {
48
51
  },
49
52
  skip: !j,
50
53
  fetchPolicy: "cache-and-network"
51
- }), q = v(() => U?.myDeveloperOrganizations?.map((e) => e) ?? [], [U?.myDeveloperOrganizations]).find((e) => e.id === j), J = me?.myBillingAccounts ?? [], Y = J.find((e) => e.id === q?.billingAccountId) ?? null, X = () => {
54
+ }), q = v(() => U?.myDeveloperOrganizations?.map((e) => e) ?? [], [U?.myDeveloperOrganizations]).find((e) => e.id === j), J = he?.getBillingAccountsByOrg ?? [], Y = J.find((e) => e.id === q?.billingAccountId) ?? null, X = () => {
52
55
  B(q?.billingAccountId ?? J.find((e) => e.isDefault)?.id ?? J[0]?.id ?? null), R(!0);
53
56
  }, Z = async () => {
54
57
  if (!(!j || !z)) {
55
58
  P(!0), I(null);
56
59
  try {
57
- await fe({
60
+ await pe({
58
61
  variables: {
59
62
  organizationId: j,
60
63
  billingAccountId: z
@@ -67,7 +70,7 @@ var k = {
67
70
  P(!1);
68
71
  }
69
72
  }
70
- }, Q = G?.developerOrgRevenueSummary, ve = [...G?.developerOrgRevenueAnalytics ?? []].sort((e, t) => new Date(e.date).getTime() - new Date(t.date).getTime()), ye = G?.developerOrgSales?.edges?.map((e) => e.node) ?? [], be = G?.developerOrgPayouts?.edges?.map((e) => e.node) ?? [], $ = ve.map((e) => ({
73
+ }, Q = G?.developerOrgRevenueSummary, ye = [...G?.developerOrgRevenueAnalytics ?? []].sort((e, t) => new Date(e.date).getTime() - new Date(t.date).getTime()), be = G?.developerOrgSales?.edges?.map((e) => e.node) ?? [], xe = G?.developerOrgPayouts?.edges?.map((e) => e.node) ?? [], $ = ye.map((e) => ({
71
74
  date: new Date(e.date).toLocaleDateString(void 0, {
72
75
  month: "short",
73
76
  day: "numeric"
@@ -78,7 +81,7 @@ var k = {
78
81
  refunds: e.refunds,
79
82
  salesCount: e.salesCount
80
83
  }));
81
- return ge && !U ? /* @__PURE__ */ D(a, {
84
+ return _e && !U ? /* @__PURE__ */ D(a, {
82
85
  title: A("devportal.revenue.title", "Revenue"),
83
86
  description: A("devportal.revenue.description", "Track real revenue, sales, and payout activity for your developer organizations"),
84
87
  children: /* @__PURE__ */ D("div", {
@@ -114,7 +117,7 @@ var k = {
114
117
  className: "flex flex-wrap gap-2",
115
118
  children: /* @__PURE__ */ O("select", {
116
119
  value: M,
117
- onChange: (e) => de(e.target.value),
120
+ onChange: (e) => fe(e.target.value),
118
121
  "aria-label": A("devportal.revenue.selectRangeAria", "Select time range"),
119
122
  className: "rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary",
120
123
  children: [
@@ -311,7 +314,7 @@ var k = {
311
314
  ]
312
315
  })]
313
316
  }),
314
- _e && !Q ? /* @__PURE__ */ D("div", {
317
+ ve && !Q ? /* @__PURE__ */ D("div", {
315
318
  className: "flex items-center justify-center py-16 text-muted-foreground",
316
319
  children: /* @__PURE__ */ D(E, { className: "h-8 w-8 animate-spin" })
317
320
  }) : Q ? /* @__PURE__ */ O(le, { children: [
@@ -351,7 +354,7 @@ var k = {
351
354
  children: /* @__PURE__ */ D(d, {
352
355
  width: "100%",
353
356
  height: 300,
354
- children: /* @__PURE__ */ O(ae, {
357
+ children: /* @__PURE__ */ O(g, {
355
358
  data: $,
356
359
  children: [
357
360
  /* @__PURE__ */ D(f, {
@@ -438,7 +441,7 @@ var k = {
438
441
  children: /* @__PURE__ */ D(d, {
439
442
  width: "100%",
440
443
  height: 280,
441
- children: /* @__PURE__ */ O(g, {
444
+ children: /* @__PURE__ */ O(_, {
442
445
  data: $,
443
446
  children: [
444
447
  /* @__PURE__ */ D(f, {
@@ -479,7 +482,7 @@ var k = {
479
482
  children: [/* @__PURE__ */ D(o, {
480
483
  title: A("devportal.revenue.recentSales", "Recent sales"),
481
484
  children: /* @__PURE__ */ D(l, {
482
- data: ye,
485
+ data: be,
483
486
  keyField: "id",
484
487
  columns: [
485
488
  {
@@ -510,7 +513,7 @@ var k = {
510
513
  }), /* @__PURE__ */ D(o, {
511
514
  title: A("devportal.revenue.payoutHistory", "Payout history"),
512
515
  children: /* @__PURE__ */ D(l, {
513
- data: be,
516
+ data: xe,
514
517
  keyField: "id",
515
518
  columns: [
516
519
  {
@@ -1 +1 @@
1
- {"version":3,"file":"RevenueDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useSearchParams } from \"react-router-dom\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n AlertCircle,\n ArrowDownToLine,\n Building2,\n Check,\n CreditCard,\n DollarSign,\n Link2,\n Loader2,\n Plus,\n Wallet,\n} from \"lucide-react\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n type GetMyOrganizationsQuery,\n type GetRevenueDashboardDataQuery,\n getErrorMessage,\n useMyBillingAccountsQuery,\n useGetMyOrganizationsQuery,\n useGetRevenueDashboardDataQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../hooks\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"30d\" | \"90d\" | \"12m\";\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n};\n\ntype RevenueSale =\n GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number][\"node\"];\ntype RevenuePayout =\n GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number][\"node\"];\n\nconst daysByRange: Record<TimeRange, number> = {\n \"30d\": 30,\n \"90d\": 90,\n \"12m\": 365,\n};\n\nexport const RevenueDashboardPage: FC = () => {\n const tr = useTr();\n const { activeOrgId } = useDevportal();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"90d\");\n const [linkingBilling, setLinkingBilling] = useState(false);\n const [linkBillingError, setLinkBillingError] = useState<string | null>(null);\n\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const [showBillingPicker, setShowBillingPicker] = useState(false);\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const [searchParams] = useSearchParams();\n const now = useMemo(() => new Date(), []);\n\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useMyBillingAccountsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n // searchParams kept for deep-link compatibility (URL ?org= still works via OrgSwitcher auto-select)\n void searchParams;\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: organizationsData,\n loading: organizationsLoading,\n error: organizationsError,\n } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n const { data, loading, error } = useGetRevenueDashboardDataQuery({\n variables: {\n organizationId: activeOrgId ?? \"\",\n period: \"monthly\",\n startDate,\n endDate: now.toISOString(),\n salesLimit: 10,\n salesOffset: 0,\n payoutsLimit: 10,\n payoutsOffset: 0,\n },\n skip: !activeOrgId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: DeveloperOrganization[] = useMemo(\n () =>\n organizationsData?.myDeveloperOrganizations?.map(\n (\n organization: GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number],\n ) => organization as unknown as DeveloperOrganization,\n ) ?? [],\n [organizationsData?.myDeveloperOrganizations],\n );\n\n const selectedOrganization = organizations.find(\n (organization) => organization.id === activeOrgId,\n );\n\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"myBillingAccounts\"][number];\n const existingBillingAccounts: BillingAccount[] =\n billingAccountsData?.myBillingAccounts ?? [];\n\n const linkedBillingAccount =\n existingBillingAccounts.find(\n (a) => a.id === selectedOrganization?.billingAccountId,\n ) ?? null;\n\n const handleOpenBillingPicker = () => {\n // Pre-select the currently linked account; fall back to default or first\n setSelectedBillingAccountId(\n selectedOrganization?.billingAccountId ??\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n setShowBillingPicker(true);\n };\n\n const handleLinkExisting = async () => {\n if (!activeOrgId || !selectedBillingAccountId) return;\n setLinkingBilling(true);\n setLinkBillingError(null);\n try {\n await linkBillingAccount({\n variables: {\n organizationId: activeOrgId,\n billingAccountId: selectedBillingAccountId,\n },\n refetchQueries: [\"GetMyOrganizations\"],\n });\n setShowBillingPicker(false);\n } catch (err) {\n setLinkBillingError(\n err instanceof Error ? err.message : \"Failed to link billing account\",\n );\n } finally {\n setLinkingBilling(false);\n }\n };\n\n const summary = data?.developerOrgRevenueSummary;\n const analytics = [...(data?.developerOrgRevenueAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n const sales: RevenueSale[] =\n data?.developerOrgSales?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n const payouts: RevenuePayout[] =\n data?.developerOrgPayouts?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n grossRevenue: entry.grossRevenue,\n netRevenue: entry.netRevenue,\n platformFees: entry.platformFees,\n refunds: entry.refunds,\n salesCount: entry.salesCount,\n }));\n\n if (organizationsLoading && !organizationsData) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-muted-foreground\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (organizationsError) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadOrgs\",\n \"Unable to load organizations\",\n )}\n description={getErrorMessage(organizationsError)}\n />\n </PageLayout>\n );\n }\n\n if (!activeOrgId) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<Building2 size={32} className=\"text-muted-foreground\" />}\n title={tr(\n \"devportal.revenue.selectOrgTitle\",\n \"Select an organization\",\n )}\n description={tr(\n \"devportal.revenue.selectOrgHint\",\n \"Use the organization switcher in the nav bar above to choose which organization's revenue to view.\",\n )}\n />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadData\",\n \"Unable to load revenue data\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={\n selectedOrganization\n ? `${tr(\"devportal.revenue.financialPerformanceFor\", \"Financial performance for\")} ${selectedOrganization.name}`\n : tr(\n \"devportal.revenue.shortDescription\",\n \"Track revenue, sales, and payouts\",\n )\n }\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.revenue.selectRangeAria\",\n \"Select time range\",\n )}\n className=\"rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"30d\">\n {tr(\"devportal.revenue.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.revenue.range.90d\", \"Last 90 days\")}\n </option>\n <option value=\"12m\">\n {tr(\"devportal.revenue.range.12m\", \"Last 12 months\")}\n </option>\n </select>\n </div>\n }\n >\n {/* Billing account link banner for orgs not yet linked */}\n {selectedOrganization && !selectedOrganization.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border-subtle bg-status-info-bg-subtle p-4 flex flex-col gap-3\">\n <div className=\"flex items-start gap-3\">\n <Link2\n size={20}\n className=\"text-accent-blue flex-shrink-0 mt-0.5\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedTitle\",\n \"Link a billing account to receive store revenue\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedDesc\",\n \"Once linked, net earnings from app sales will appear in your billing credits — you can spend them on platform services or withdraw to your bank.\",\n )}\n </p>\n {linkBillingError && (\n <p className=\"mt-2 text-sm text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={linkingBilling || billingAccountsLoading}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 flex-shrink-0\"\n >\n {linkingBilling || billingAccountsLoading ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Link2 size={14} />\n )}\n {linkingBilling\n ? tr(\"devportal.revenue.linking\", \"Linking...\")\n : tr(\n \"devportal.revenue.linkBillingAccount\",\n \"Link Billing Account\",\n )}\n </button>\n </div>\n\n {/* No billing accounts message */}\n {showBillingPicker && existingBillingAccounts.length === 0 && (\n <div className=\"rounded-lg border border-border bg-card p-4 ml-8 text-sm text-muted-foreground\">\n {tr(\n \"devportal.revenue.noBillingAccounts\",\n \"You don't have any billing accounts yet. Create one from your account billing settings first.\",\n )}\n </div>\n )}\n\n {/* Billing account picker — shown when user has existing accounts */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border bg-card p-4 ml-8 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-primary/5 text-foreground\"\n : \"border-border hover:bg-accent text-foreground\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Linked billing account info — shown when billing is already linked */}\n {selectedOrganization?.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border bg-card p-3 flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <CreditCard\n size={16}\n className=\"text-muted-foreground flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {linkedBillingAccount?.name ??\n tr(\"devportal.revenue.billingAccount\", \"Billing account\")}\n </p>\n <p className=\"text-xs text-muted-foreground truncate\">\n {linkedBillingAccount\n ? `${linkedBillingAccount.currency}${linkedBillingAccount.email ? ` · ${linkedBillingAccount.email}` : \"\"}`\n : selectedOrganization.billingAccountId}\n </p>\n </div>\n {!showBillingPicker && (\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={billingAccountsLoading}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors flex-shrink-0 disabled:opacity-50\"\n >\n {tr(\"devportal.revenue.changeBillingAccount\", \"Change\")}\n </button>\n )}\n </div>\n {/* Picker for changing the linked account */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border bg-background p-4 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-primary/5 text-foreground\"\n : \"border-border hover:bg-accent text-foreground\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n {linkBillingError && (\n <p className=\"text-xs text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n )}\n </div>\n )}\n\n {loading && !summary ? (\n <div className=\"flex items-center justify-center py-16 text-muted-foreground\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : summary ? (\n <>\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.revenue.grossRevenue\", \"Gross Revenue\")}\n value={`$${summary.totalGrossRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.netRevenue\", \"Net Revenue\")}\n value={`$${summary.totalNetRevenue.toLocaleString()}`}\n icon={<Wallet size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.pendingBalance\", \"Pending Balance\")}\n value={`$${summary.pendingBalance.toLocaleString()}`}\n icon={<CreditCard size={20} />}\n description={\n summary.nextPayoutDate\n ? `${tr(\"devportal.revenue.nextPayout\", \"Next payout\")} ${new Date(summary.nextPayoutDate).toLocaleDateString()}`\n : tr(\n \"devportal.revenue.noPayoutScheduled\",\n \"No payout scheduled\",\n )\n }\n />\n <StatCard\n title={tr(\"devportal.revenue.platformFees\", \"Platform Fees\")}\n value={`$${summary.totalPlatformFees.toLocaleString()}`}\n icon={<ArrowDownToLine size={20} />}\n description={`${summary.totalRefundsCount} ${tr(\"devportal.revenue.refunds\", \"refunds\")}`}\n />\n </StatCardGrid>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.revenueTrend\", \"Revenue trend\")}\n >\n <div className=\"rounded-lg border bg-card p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"grossRevenue\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"netRevenue\"\n stroke={chartColors.secondary}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.revenue.topApps\",\n \"Top applications by revenue\",\n )}\n >\n {summary.topApps.length > 0 ? (\n <div className=\"space-y-2\">\n {summary.topApps.map(\n (\n application: GetRevenueDashboardDataQuery[\"developerOrgRevenueSummary\"][\"topApps\"][number],\n ) => (\n <div\n key={application.applicationId}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"font-medium\">\n {application.applicationName}\n </p>\n <p className=\"text-sm text-muted-foreground\">\n {application.salesCount}{\" \"}\n {tr(\"devportal.revenue.sales\", \"sales\")}\n </p>\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">\n ${application.grossRevenue.toLocaleString()}\n </p>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\"devportal.revenue.net\", \"Net\")} $\n {application.netRevenue.toLocaleString()}\n </p>\n </div>\n </div>\n </div>\n ),\n )}\n </div>\n ) : (\n <EmptyState\n icon={<Building2 size={24} />}\n title={tr(\n \"devportal.revenue.noLeadersTitle\",\n \"No revenue leaders yet\",\n )}\n description={tr(\n \"devportal.revenue.noLeadersDescription\",\n \"Top-performing applications will appear here once revenue is recorded.\",\n )}\n />\n )}\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.revenue.salesVolume\", \"Sales volume\")}\n >\n <div className=\"rounded-lg border bg-card p-4\">\n <ResponsiveContainer width=\"100%\" height={280}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"salesCount\"\n fill={chartColors.tertiary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n </div>\n </PageSection>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.recentSales\", \"Recent sales\")}\n >\n <DataTable\n data={sales}\n keyField=\"id\"\n columns={[\n {\n key: \"application\",\n header: tr(\"devportal.revenue.application\", \"Application\"),\n render: (sale) =>\n sale.application?.name ||\n sale.planName ||\n tr(\"devportal.common.unknown\", \"Unknown\"),\n },\n {\n key: \"grossAmount\",\n header: tr(\"devportal.revenue.gross\", \"Gross\"),\n render: (sale) => `$${sale.grossAmount.toLocaleString()}`,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.net\", \"Net\"),\n render: (sale) => `$${sale.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (sale) => (\n <StatusBadge status={sale.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.revenue.payoutHistory\", \"Payout history\")}\n >\n <DataTable\n data={payouts}\n keyField=\"id\"\n columns={[\n {\n key: \"periodLabel\",\n header: tr(\"devportal.revenue.period\", \"Period\"),\n render: (payout) => payout.periodLabel,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.netPayout\", \"Net payout\"),\n render: (payout) => `$${payout.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (payout) => (\n <StatusBadge status={payout.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n </>\n ) : (\n <EmptyState\n icon={<DollarSign size={32} />}\n title={tr(\"devportal.revenue.noDataTitle\", \"No revenue data yet\")}\n description={tr(\n \"devportal.revenue.noDataDescription\",\n \"Revenue metrics will appear after this organization starts recording marketplace sales.\",\n )}\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"RevenueDashboardPage.js","names":[],"sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useMemo, useState } from \"react\";\nimport { useSearchParams } from \"react-router-dom\";\nimport {\n Bar,\n BarChart,\n CartesianGrid,\n Line,\n LineChart,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n AlertCircle,\n ArrowDownToLine,\n Building2,\n Check,\n CreditCard,\n DollarSign,\n Link2,\n Loader2,\n Wallet,\n} from \"lucide-react\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatCard, StatCardGrid } from \"../components/StatCard\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n type GetMyOrganizationsQuery,\n type GetRevenueDashboardDataQuery,\n getErrorMessage,\n useGetBillingAccountsByOrgQuery,\n useGetMyOrganizationsQuery,\n useGetRevenueDashboardDataQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../hooks\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype TimeRange = \"30d\" | \"90d\" | \"12m\";\n\nconst chartColors = {\n primary: \"var(--color-chart-1)\",\n secondary: \"var(--color-chart-2)\",\n tertiary: \"var(--color-chart-4)\",\n};\n\ntype RevenueSale =\n GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number][\"node\"];\ntype RevenuePayout =\n GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number][\"node\"];\n\nconst daysByRange: Record<TimeRange, number> = {\n \"30d\": 30,\n \"90d\": 90,\n \"12m\": 365,\n};\n\nexport const RevenueDashboardPage: FC = () => {\n const tr = useTr();\n const { activeOrgId, tenantId } = useDevportal();\n const [timeRange, setTimeRange] = useState<TimeRange>(\"90d\");\n const [linkingBilling, setLinkingBilling] = useState(false);\n const [linkBillingError, setLinkBillingError] = useState<string | null>(null);\n\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const [showBillingPicker, setShowBillingPicker] = useState(false);\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const [searchParams] = useSearchParams();\n const now = useMemo(() => new Date(), []);\n\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useGetBillingAccountsByOrgQuery({\n fetchPolicy: \"cache-and-network\",\n context: { headers: { \"x-org-id\": tenantId ?? \"\" } },\n });\n // searchParams kept for deep-link compatibility (URL ?org= still works via OrgSwitcher auto-select)\n void searchParams;\n const startDate = useMemo(() => {\n const nextDate = new Date(now);\n nextDate.setDate(nextDate.getDate() - daysByRange[timeRange]);\n return nextDate.toISOString();\n }, [now, timeRange]);\n\n const {\n data: organizationsData,\n loading: organizationsLoading,\n error: organizationsError,\n } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n const { data, loading, error } = useGetRevenueDashboardDataQuery({\n variables: {\n organizationId: activeOrgId ?? \"\",\n period: \"monthly\",\n startDate,\n endDate: now.toISOString(),\n salesLimit: 10,\n salesOffset: 0,\n payoutsLimit: 10,\n payoutsOffset: 0,\n },\n skip: !activeOrgId,\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations: DeveloperOrganization[] = useMemo(\n () =>\n organizationsData?.myDeveloperOrganizations?.map(\n (\n organization: GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number],\n ) => organization as unknown as DeveloperOrganization,\n ) ?? [],\n [organizationsData?.myDeveloperOrganizations],\n );\n\n const selectedOrganization = organizations.find(\n (organization) => organization.id === activeOrgId,\n );\n\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"getBillingAccountsByOrg\"][number];\n const existingBillingAccounts: BillingAccount[] =\n billingAccountsData?.getBillingAccountsByOrg ?? [];\n\n const linkedBillingAccount =\n existingBillingAccounts.find(\n (a) => a.id === selectedOrganization?.billingAccountId,\n ) ?? null;\n\n const handleOpenBillingPicker = () => {\n // Pre-select the currently linked account; fall back to default or first\n setSelectedBillingAccountId(\n selectedOrganization?.billingAccountId ??\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n setShowBillingPicker(true);\n };\n\n const handleLinkExisting = async () => {\n if (!activeOrgId || !selectedBillingAccountId) return;\n setLinkingBilling(true);\n setLinkBillingError(null);\n try {\n await linkBillingAccount({\n variables: {\n organizationId: activeOrgId,\n billingAccountId: selectedBillingAccountId,\n },\n refetchQueries: [\"GetMyOrganizations\"],\n });\n setShowBillingPicker(false);\n } catch (err) {\n setLinkBillingError(\n err instanceof Error ? err.message : \"Failed to link billing account\",\n );\n } finally {\n setLinkingBilling(false);\n }\n };\n\n const summary = data?.developerOrgRevenueSummary;\n const analytics = [...(data?.developerOrgRevenueAnalytics ?? [])].sort(\n (left, right) =>\n new Date(left.date).getTime() - new Date(right.date).getTime(),\n );\n const sales: RevenueSale[] =\n data?.developerOrgSales?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgSales\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n const payouts: RevenuePayout[] =\n data?.developerOrgPayouts?.edges?.map(\n (\n edge: GetRevenueDashboardDataQuery[\"developerOrgPayouts\"][\"edges\"][number],\n ) => edge.node,\n ) ?? [];\n\n const chartData = analytics.map((entry) => ({\n date: new Date(entry.date).toLocaleDateString(undefined, {\n month: \"short\",\n day: \"numeric\",\n }),\n grossRevenue: entry.grossRevenue,\n netRevenue: entry.netRevenue,\n platformFees: entry.platformFees,\n refunds: entry.refunds,\n salesCount: entry.salesCount,\n }));\n\n if (organizationsLoading && !organizationsData) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <div className=\"flex items-center justify-center py-16 text-muted-foreground\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n </PageLayout>\n );\n }\n\n if (organizationsError) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadOrgs\",\n \"Unable to load organizations\",\n )}\n description={getErrorMessage(organizationsError)}\n />\n </PageLayout>\n );\n }\n\n if (!activeOrgId) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<Building2 size={32} className=\"text-muted-foreground\" />}\n title={tr(\n \"devportal.revenue.selectOrgTitle\",\n \"Select an organization\",\n )}\n description={tr(\n \"devportal.revenue.selectOrgHint\",\n \"Use the organization switcher in the nav bar above to choose which organization's revenue to view.\",\n )}\n />\n </PageLayout>\n );\n }\n\n if (error) {\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={tr(\n \"devportal.revenue.description\",\n \"Track real revenue, sales, and payout activity for your developer organizations\",\n )}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.revenue.errorLoadData\",\n \"Unable to load revenue data\",\n )}\n description={getErrorMessage(error)}\n />\n </PageLayout>\n );\n }\n\n return (\n <PageLayout\n title={tr(\"devportal.revenue.title\", \"Revenue\")}\n description={\n selectedOrganization\n ? `${tr(\"devportal.revenue.financialPerformanceFor\", \"Financial performance for\")} ${selectedOrganization.name}`\n : tr(\n \"devportal.revenue.shortDescription\",\n \"Track revenue, sales, and payouts\",\n )\n }\n actions={\n <div className=\"flex flex-wrap gap-2\">\n <select\n value={timeRange}\n onChange={(event) => setTimeRange(event.target.value as TimeRange)}\n aria-label={tr(\n \"devportal.revenue.selectRangeAria\",\n \"Select time range\",\n )}\n className=\"rounded-md border bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"30d\">\n {tr(\"devportal.revenue.range.30d\", \"Last 30 days\")}\n </option>\n <option value=\"90d\">\n {tr(\"devportal.revenue.range.90d\", \"Last 90 days\")}\n </option>\n <option value=\"12m\">\n {tr(\"devportal.revenue.range.12m\", \"Last 12 months\")}\n </option>\n </select>\n </div>\n }\n >\n {/* Billing account link banner for orgs not yet linked */}\n {selectedOrganization && !selectedOrganization.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border-subtle bg-status-info-bg-subtle p-4 flex flex-col gap-3\">\n <div className=\"flex items-start gap-3\">\n <Link2\n size={20}\n className=\"text-accent-blue flex-shrink-0 mt-0.5\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedTitle\",\n \"Link a billing account to receive store revenue\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-status-info-text\">\n {tr(\n \"devportal.revenue.billingNotLinkedDesc\",\n \"Once linked, net earnings from app sales will appear in your billing credits — you can spend them on platform services or withdraw to your bank.\",\n )}\n </p>\n {linkBillingError && (\n <p className=\"mt-2 text-sm text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={linkingBilling || billingAccountsLoading}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50 flex-shrink-0\"\n >\n {linkingBilling || billingAccountsLoading ? (\n <Loader2 size={14} className=\"animate-spin\" />\n ) : (\n <Link2 size={14} />\n )}\n {linkingBilling\n ? tr(\"devportal.revenue.linking\", \"Linking...\")\n : tr(\n \"devportal.revenue.linkBillingAccount\",\n \"Link Billing Account\",\n )}\n </button>\n </div>\n\n {/* No billing accounts message */}\n {showBillingPicker && existingBillingAccounts.length === 0 && (\n <div className=\"rounded-lg border border-border bg-card p-4 ml-8 text-sm text-muted-foreground\">\n {tr(\n \"devportal.revenue.noBillingAccounts\",\n \"You don't have any billing accounts yet. Create one from your account billing settings first.\",\n )}\n </div>\n )}\n\n {/* Billing account picker — shown when user has existing accounts */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border bg-card p-4 ml-8 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-primary/5 text-foreground\"\n : \"border-border hover:bg-accent text-foreground\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Linked billing account info — shown when billing is already linked */}\n {selectedOrganization?.billingAccountId && (\n <div className=\"mb-6 rounded-lg border border-border bg-card p-3 flex flex-col gap-3\">\n <div className=\"flex items-center gap-3\">\n <CreditCard\n size={16}\n className=\"text-muted-foreground flex-shrink-0\"\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium truncate\">\n {linkedBillingAccount?.name ??\n tr(\"devportal.revenue.billingAccount\", \"Billing account\")}\n </p>\n <p className=\"text-xs text-muted-foreground truncate\">\n {linkedBillingAccount\n ? `${linkedBillingAccount.currency}${linkedBillingAccount.email ? ` · ${linkedBillingAccount.email}` : \"\"}`\n : selectedOrganization.billingAccountId}\n </p>\n </div>\n {!showBillingPicker && (\n <button\n type=\"button\"\n onClick={handleOpenBillingPicker}\n disabled={billingAccountsLoading}\n className=\"text-xs text-muted-foreground hover:text-foreground transition-colors flex-shrink-0 disabled:opacity-50\"\n >\n {tr(\"devportal.revenue.changeBillingAccount\", \"Change\")}\n </button>\n )}\n </div>\n {/* Picker for changing the linked account */}\n {showBillingPicker && existingBillingAccounts.length > 0 && (\n <div className=\"rounded-lg border border-border bg-background p-4 space-y-3\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.revenue.chooseBillingAccount\",\n \"Choose a billing account to link\",\n )}\n </p>\n <div className=\"space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n onClick={() =>\n setSelectedBillingAccountId(account.id ?? null)\n }\n className={cn(\n \"flex w-full items-center gap-3 rounded-md border px-3 py-2.5 text-sm text-left transition-colors\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-primary/5 text-foreground\"\n : \"border-border hover:bg-accent text-foreground\",\n )}\n >\n <Check\n size={14}\n className={cn(\n \"flex-shrink-0\",\n selectedBillingAccountId === account.id\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"font-medium truncate\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-muted-foreground\">\n {tr(\"devportal.revenue.defaultAccount\", \"Default\")}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n <div className=\"flex items-center justify-end gap-2 pt-1\">\n <button\n type=\"button\"\n onClick={() => {\n setShowBillingPicker(false);\n setLinkBillingError(null);\n }}\n className=\"rounded-md px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-accent transition-colors\"\n >\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n disabled={linkingBilling || !selectedBillingAccountId}\n onClick={() => void handleLinkExisting()}\n className=\"inline-flex items-center gap-1.5 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {linkingBilling ? (\n <Loader2 size={13} className=\"animate-spin\" />\n ) : (\n <Link2 size={13} />\n )}\n {tr(\"devportal.revenue.confirm\", \"Confirm\")}\n </button>\n </div>\n {linkBillingError && (\n <p className=\"text-xs text-status-error-text\">\n {linkBillingError}\n </p>\n )}\n </div>\n )}\n </div>\n )}\n\n {loading && !summary ? (\n <div className=\"flex items-center justify-center py-16 text-muted-foreground\">\n <Loader2 className=\"h-8 w-8 animate-spin\" />\n </div>\n ) : summary ? (\n <>\n <StatCardGrid columns={4}>\n <StatCard\n title={tr(\"devportal.revenue.grossRevenue\", \"Gross Revenue\")}\n value={`$${summary.totalGrossRevenue.toLocaleString()}`}\n icon={<DollarSign size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.netRevenue\", \"Net Revenue\")}\n value={`$${summary.totalNetRevenue.toLocaleString()}`}\n icon={<Wallet size={20} />}\n />\n <StatCard\n title={tr(\"devportal.revenue.pendingBalance\", \"Pending Balance\")}\n value={`$${summary.pendingBalance.toLocaleString()}`}\n icon={<CreditCard size={20} />}\n description={\n summary.nextPayoutDate\n ? `${tr(\"devportal.revenue.nextPayout\", \"Next payout\")} ${new Date(summary.nextPayoutDate).toLocaleDateString()}`\n : tr(\n \"devportal.revenue.noPayoutScheduled\",\n \"No payout scheduled\",\n )\n }\n />\n <StatCard\n title={tr(\"devportal.revenue.platformFees\", \"Platform Fees\")}\n value={`$${summary.totalPlatformFees.toLocaleString()}`}\n icon={<ArrowDownToLine size={20} />}\n description={`${summary.totalRefundsCount} ${tr(\"devportal.revenue.refunds\", \"refunds\")}`}\n />\n </StatCardGrid>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.revenueTrend\", \"Revenue trend\")}\n >\n <div className=\"rounded-lg border bg-card p-4\">\n <ResponsiveContainer width=\"100%\" height={300}>\n <LineChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Line\n type=\"monotone\"\n dataKey=\"grossRevenue\"\n stroke={chartColors.primary}\n strokeWidth={2}\n dot={false}\n />\n <Line\n type=\"monotone\"\n dataKey=\"netRevenue\"\n stroke={chartColors.secondary}\n strokeWidth={2}\n dot={false}\n />\n </LineChart>\n </ResponsiveContainer>\n </div>\n </PageSection>\n\n <PageSection\n title={tr(\n \"devportal.revenue.topApps\",\n \"Top applications by revenue\",\n )}\n >\n {summary.topApps.length > 0 ? (\n <div className=\"space-y-2\">\n {summary.topApps.map(\n (\n application: GetRevenueDashboardDataQuery[\"developerOrgRevenueSummary\"][\"topApps\"][number],\n ) => (\n <div\n key={application.applicationId}\n className=\"rounded-lg border bg-card p-4\"\n >\n <div className=\"flex items-start justify-between gap-3\">\n <div>\n <p className=\"font-medium\">\n {application.applicationName}\n </p>\n <p className=\"text-sm text-muted-foreground\">\n {application.salesCount}{\" \"}\n {tr(\"devportal.revenue.sales\", \"sales\")}\n </p>\n </div>\n <div className=\"text-right\">\n <p className=\"font-semibold\">\n ${application.grossRevenue.toLocaleString()}\n </p>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\"devportal.revenue.net\", \"Net\")} $\n {application.netRevenue.toLocaleString()}\n </p>\n </div>\n </div>\n </div>\n ),\n )}\n </div>\n ) : (\n <EmptyState\n icon={<Building2 size={24} />}\n title={tr(\n \"devportal.revenue.noLeadersTitle\",\n \"No revenue leaders yet\",\n )}\n description={tr(\n \"devportal.revenue.noLeadersDescription\",\n \"Top-performing applications will appear here once revenue is recorded.\",\n )}\n />\n )}\n </PageSection>\n </div>\n\n <PageSection\n title={tr(\"devportal.revenue.salesVolume\", \"Sales volume\")}\n >\n <div className=\"rounded-lg border bg-card p-4\">\n <ResponsiveContainer width=\"100%\" height={280}>\n <BarChart data={chartData}>\n <CartesianGrid\n strokeDasharray=\"3 3\"\n stroke=\"var(--color-chart-grid)\"\n />\n <XAxis\n dataKey=\"date\"\n stroke=\"var(--color-chart-axis)\"\n fontSize={12}\n />\n <YAxis stroke=\"var(--color-chart-axis)\" fontSize={12} />\n <Tooltip\n contentStyle={{\n backgroundColor: \"var(--color-card)\",\n border: \"1px solid var(--color-border-default)\",\n borderRadius: 12,\n }}\n />\n <Bar\n dataKey=\"salesCount\"\n fill={chartColors.tertiary}\n radius={[6, 6, 0, 0]}\n />\n </BarChart>\n </ResponsiveContainer>\n </div>\n </PageSection>\n\n <div className=\"grid gap-6 xl:grid-cols-2\">\n <PageSection\n title={tr(\"devportal.revenue.recentSales\", \"Recent sales\")}\n >\n <DataTable\n data={sales}\n keyField=\"id\"\n columns={[\n {\n key: \"application\",\n header: tr(\"devportal.revenue.application\", \"Application\"),\n render: (sale) =>\n sale.application?.name ||\n sale.planName ||\n tr(\"devportal.common.unknown\", \"Unknown\"),\n },\n {\n key: \"grossAmount\",\n header: tr(\"devportal.revenue.gross\", \"Gross\"),\n render: (sale) => `$${sale.grossAmount.toLocaleString()}`,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.net\", \"Net\"),\n render: (sale) => `$${sale.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (sale) => (\n <StatusBadge status={sale.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n\n <PageSection\n title={tr(\"devportal.revenue.payoutHistory\", \"Payout history\")}\n >\n <DataTable\n data={payouts}\n keyField=\"id\"\n columns={[\n {\n key: \"periodLabel\",\n header: tr(\"devportal.revenue.period\", \"Period\"),\n render: (payout) => payout.periodLabel,\n },\n {\n key: \"netAmount\",\n header: tr(\"devportal.revenue.netPayout\", \"Net payout\"),\n render: (payout) => `$${payout.netAmount.toLocaleString()}`,\n },\n {\n key: \"status\",\n header: tr(\"devportal.revenue.status\", \"Status\"),\n render: (payout) => (\n <StatusBadge status={payout.status} type=\"app\" />\n ),\n },\n ]}\n />\n </PageSection>\n </div>\n </>\n ) : (\n <EmptyState\n icon={<DollarSign size={32} />}\n title={tr(\"devportal.revenue.noDataTitle\", \"No revenue data yet\")}\n description={tr(\n \"devportal.revenue.noDataDescription\",\n \"Revenue metrics will appear after this organization starts recording marketplace sales.\",\n )}\n />\n )}\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA8CA,IAAM,IAAc;CAClB,SAAS;CACT,WAAW;CACX,UAAU;CACX,EAOK,KAAyC;CAC7C,OAAO;CACP,OAAO;CACP,OAAO;CACR,EAEY,UAAiC;CAC5C,IAAM,IAAK,IAAO,EACZ,EAAE,gBAAa,iBAAa,GAAc,EAC1C,CAAC,GAAW,MAAgB,EAAoB,MAAM,EACtD,CAAC,GAAgB,KAAqB,EAAS,GAAM,EACrD,CAAC,GAAkB,KAAuB,EAAwB,KAAK,EAEvE,CAAC,MAAsB,GAAqC,EAC5D,CAAC,GAAmB,KAAwB,EAAS,GAAM,EAC3D,CAAC,GAA0B,KAA+B,EAE9D,KAAK,EACD,CAAC,MAAgB,IAAiB,EAClC,IAAM,wBAAc,IAAI,MAAM,EAAE,EAAE,CAAC,EAEnC,EAAE,MAAM,IAAqB,SAAS,MAC1C,GAAgC;EAC9B,aAAa;EACb,SAAS,EAAE,SAAS,EAAE,YAAY,MAAY,IAAI,EAAE;EACrD,CAAC,EAGE,KAAY,QAAc;EAC9B,IAAM,IAAW,IAAI,KAAK,EAAI;AAE9B,SADA,EAAS,QAAQ,EAAS,SAAS,GAAG,GAAY,GAAW,EACtD,EAAS,aAAa;IAC5B,CAAC,GAAK,EAAU,CAAC,EAEd,EACJ,MAAM,GACN,SAAS,IACT,OAAO,MACL,GAA2B,EAC7B,aAAa,qBACd,CAAC,EACI,EAAE,SAAM,aAAS,aAAU,GAAgC;EAC/D,WAAW;GACT,gBAAgB,KAAe;GAC/B,QAAQ;GACR;GACA,SAAS,EAAI,aAAa;GAC1B,YAAY;GACZ,aAAa;GACb,cAAc;GACd,eAAe;GAChB;EACD,MAAM,CAAC;EACP,aAAa;EACd,CAAC,EAYI,IAVyC,QAE3C,GAAmB,0BAA0B,KAEzC,MACG,EACN,IAAI,EAAE,EACT,CAAC,GAAmB,yBAAyB,CAC9C,CAE0C,MACxC,MAAiB,EAAa,OAAO,EACvC,EAKK,IACJ,IAAqB,2BAA2B,EAAE,EAE9C,IACJ,EAAwB,MACrB,MAAM,EAAE,OAAO,GAAsB,iBACvC,IAAI,MAED,UAAgC;AAQpC,EANA,EACE,GAAsB,oBACpB,EAAwB,MAAM,MAAM,EAAE,UAAU,EAAE,MAClD,EAAwB,IAAI,MAC5B,KACH,EACD,EAAqB,GAAK;IAGtB,IAAqB,YAAY;AACjC,SAAC,KAAe,CAAC,IAErB;GADA,EAAkB,GAAK,EACvB,EAAoB,KAAK;AACzB,OAAI;AAQF,IAPA,MAAM,GAAmB;KACvB,WAAW;MACT,gBAAgB;MAChB,kBAAkB;MACnB;KACD,gBAAgB,CAAC,qBAAqB;KACvC,CAAC,EACF,EAAqB,GAAM;YACpB,GAAK;AACZ,MACE,aAAe,QAAQ,EAAI,UAAU,iCACtC;aACO;AACR,MAAkB,GAAM;;;IAItB,IAAU,GAAM,4BAChB,KAAY,CAAC,GAAI,GAAM,gCAAgC,EAAE,CAAE,CAAC,MAC/D,GAAM,MACL,IAAI,KAAK,EAAK,KAAK,CAAC,SAAS,GAAG,IAAI,KAAK,EAAM,KAAK,CAAC,SAAS,CACjE,EACK,KACJ,GAAM,mBAAmB,OAAO,KAE5B,MACG,EAAK,KACX,IAAI,EAAE,EACH,KACJ,GAAM,qBAAqB,OAAO,KAE9B,MACG,EAAK,KACX,IAAI,EAAE,EAEH,IAAY,GAAU,KAAK,OAAW;EAC1C,MAAM,IAAI,KAAK,EAAM,KAAK,CAAC,mBAAmB,KAAA,GAAW;GACvD,OAAO;GACP,KAAK;GACN,CAAC;EACF,cAAc,EAAM;EACpB,YAAY,EAAM;EAClB,cAAc,EAAM;EACpB,SAAS,EAAM;EACf,YAAY,EAAM;EACnB,EAAE;AAoFH,QAlFI,MAAwB,CAAC,IAEzB,kBAAC,GAAD;EACE,OAAO,EAAG,2BAA2B,UAAU;EAC/C,aAAa,EACX,iCACA,kFACD;YAED,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA;GACxC,CAAA;EACK,CAAA,GAIb,IAEA,kBAAC,GAAD;EACE,OAAO,EAAG,2BAA2B,UAAU;EAC/C,aAAa,EACX,iCACA,kFACD;YAED,kBAAC,GAAD;GACE,MAAM,kBAAC,GAAD;IAAa,MAAM;IAAI,WAAU;IAA2B,CAAA;GAClE,OAAO,EACL,mCACA,+BACD;GACD,aAAa,EAAgB,EAAmB;GAChD,CAAA;EACS,CAAA,GAIZ,IAwBD,IAEA,kBAAC,GAAD;EACE,OAAO,EAAG,2BAA2B,UAAU;EAC/C,aAAa,EACX,iCACA,kFACD;YAED,kBAAC,GAAD;GACE,MAAM,kBAAC,GAAD;IAAa,MAAM;IAAI,WAAU;IAA2B,CAAA;GAClE,OAAO,EACL,mCACA,8BACD;GACD,aAAa,EAAgB,EAAM;GACnC,CAAA;EACS,CAAA,GAKf,kBAAC,GAAD;EACE,OAAO,EAAG,2BAA2B,UAAU;EAC/C,aACE,IACI,GAAG,EAAG,6CAA6C,4BAA4B,CAAC,GAAG,EAAqB,SACxG,EACE,sCACA,oCACD;EAEP,SACE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,UAAD;IACE,OAAO;IACP,WAAW,MAAU,GAAa,EAAM,OAAO,MAAmB;IAClE,cAAY,EACV,qCACA,oBACD;IACD,WAAU;cAPZ;KASE,kBAAC,UAAD;MAAQ,OAAM;gBACX,EAAG,+BAA+B,eAAe;MAC3C,CAAA;KACT,kBAAC,UAAD;MAAQ,OAAM;gBACX,EAAG,+BAA+B,eAAe;MAC3C,CAAA;KACT,kBAAC,UAAD;MAAQ,OAAM;gBACX,EAAG,+BAA+B,iBAAiB;MAC7C,CAAA;KACF;;GACL,CAAA;YA/BV;GAmCG,KAAwB,CAAC,EAAqB,oBAC7C,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,GAAD;QACE,MAAM;QACN,WAAU;QACV,CAAA;OACF,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,KAAD;UAAG,WAAU;oBACV,EACC,2CACA,kDACD;UACC,CAAA;SACJ,kBAAC,KAAD;UAAG,WAAU;oBACV,EACC,0CACA,mJACD;UACC,CAAA;SACH,KACC,kBAAC,KAAD;UAAG,WAAU;oBACV;UACC,CAAA;SAEF;;OACN,kBAAC,UAAD;QACE,MAAK;QACL,SAAS;QACT,UAAU,KAAkB;QAC5B,WAAU;kBAJZ,CAMG,KAAkB,IACjB,kBAAC,GAAD;SAAS,MAAM;SAAI,WAAU;SAAiB,CAAA,GAE9C,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA,EAEpB,IACG,EAAG,6BAA6B,aAAa,GAC7C,EACE,wCACA,uBACD,CACE;;OACL;;KAGL,KAAqB,EAAwB,WAAW,KACvD,kBAAC,OAAD;MAAK,WAAU;gBACZ,EACC,uCACA,gGACD;MACG,CAAA;KAIP,KAAqB,EAAwB,SAAS,KACrD,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,0CACA,mCACD;QACC,CAAA;OACJ,kBAAC,OAAD;QAAK,WAAU;kBACZ,EAAwB,KAAK,MAC5B,kBAAC,UAAD;SAEE,MAAK;SACL,eACE,EAA4B,EAAQ,MAAM,KAAK;SAEjD,WAAW,EACT,oGACA,MAA6B,EAAQ,KACjC,gDACA,gDACL;mBAXH,CAaE,kBAAC,GAAD;UACE,MAAM;UACN,WAAW,EACT,iBACA,MAA6B,EAAQ,KACjC,6BACA,YACL;UACD,CAAA,EACF,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAwB,EAAQ;WAAS,CAAA,EACrD,EAAQ,aACP,kBAAC,KAAD;WAAG,WAAU;qBACV,EAAG,oCAAoC,UAAU;WAChD,CAAA,CAEF;YACC;WA7BF,EAAQ,GA6BN,CACT;QACE,CAAA;OACN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,UAAD;SACE,MAAK;SACL,eAAe;AAEb,UADA,EAAqB,GAAM,EAC3B,EAAoB,KAAK;;SAE3B,WAAU;mBAET,EAAG,oBAAoB,SAAS;SAC1B,CAAA,EACT,kBAAC,UAAD;SACE,MAAK;SACL,UAAU,KAAkB,CAAC;SAC7B,eAAe,KAAK,GAAoB;SACxC,WAAU;mBAJZ,CAMG,IACC,kBAAC,GAAD;UAAS,MAAM;UAAI,WAAU;UAAiB,CAAA,GAE9C,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA,EAEpB,EAAG,6BAA6B,UAAU,CACpC;WACL;;OACF;;KAEJ;;GAIP,GAAsB,oBACrB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,GAAD;OACE,MAAM;OACN,WAAU;OACV,CAAA;MACF,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBACV,GAAsB,QACrB,EAAG,oCAAoC,kBAAkB;QACzD,CAAA,EACJ,kBAAC,KAAD;QAAG,WAAU;kBACV,IACG,GAAG,EAAqB,WAAW,EAAqB,QAAQ,MAAM,EAAqB,UAAU,OACrG,EAAqB;QACvB,CAAA,CACA;;MACL,CAAC,KACA,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,UAAU;OACV,WAAU;iBAET,EAAG,0CAA0C,SAAS;OAChD,CAAA;MAEP;QAEL,KAAqB,EAAwB,SAAS,KACrD,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,0CACA,mCACD;OACC,CAAA;MACJ,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAwB,KAAK,MAC5B,kBAAC,UAAD;QAEE,MAAK;QACL,eACE,EAA4B,EAAQ,MAAM,KAAK;QAEjD,WAAW,EACT,oGACA,MAA6B,EAAQ,KACjC,gDACA,gDACL;kBAXH,CAaE,kBAAC,GAAD;SACE,MAAM;SACN,WAAW,EACT,iBACA,MAA6B,EAAQ,KACjC,6BACA,YACL;SACD,CAAA,EACF,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,KAAD;UAAG,WAAU;oBAAwB,EAAQ;UAAS,CAAA,EACrD,EAAQ,aACP,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAG,oCAAoC,UAAU;UAChD,CAAA,CAEF;WACC;UA7BF,EAAQ,GA6BN,CACT;OACE,CAAA;MACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,UAAD;QACE,MAAK;QACL,eAAe;AAEb,SADA,EAAqB,GAAM,EAC3B,EAAoB,KAAK;;QAE3B,WAAU;kBAET,EAAG,oBAAoB,SAAS;QAC1B,CAAA,EACT,kBAAC,UAAD;QACE,MAAK;QACL,UAAU,KAAkB,CAAC;QAC7B,eAAe,KAAK,GAAoB;QACxC,WAAU;kBAJZ,CAMG,IACC,kBAAC,GAAD;SAAS,MAAM;SAAI,WAAU;SAAiB,CAAA,GAE9C,kBAAC,GAAD,EAAO,MAAM,IAAM,CAAA,EAEpB,EAAG,6BAA6B,UAAU,CACpC;UACL;;MACL,KACC,kBAAC,KAAD;OAAG,WAAU;iBACV;OACC,CAAA;MAEF;OAEJ;;GAGP,MAAW,CAAC,IACX,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA;IACxC,CAAA,GACJ,IACF,kBAAA,IAAA,EAAA,UAAA;IACE,kBAAC,IAAD;KAAc,SAAS;eAAvB;MACE,kBAAC,GAAD;OACE,OAAO,EAAG,kCAAkC,gBAAgB;OAC5D,OAAO,IAAI,EAAQ,kBAAkB,gBAAgB;OACrD,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;OAC9B,CAAA;MACF,kBAAC,GAAD;OACE,OAAO,EAAG,gCAAgC,cAAc;OACxD,OAAO,IAAI,EAAQ,gBAAgB,gBAAgB;OACnD,MAAM,kBAAC,IAAD,EAAQ,MAAM,IAAM,CAAA;OAC1B,CAAA;MACF,kBAAC,GAAD;OACE,OAAO,EAAG,oCAAoC,kBAAkB;OAChE,OAAO,IAAI,EAAQ,eAAe,gBAAgB;OAClD,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;OAC9B,aACE,EAAQ,iBACJ,GAAG,EAAG,gCAAgC,cAAc,CAAC,GAAG,IAAI,KAAK,EAAQ,eAAe,CAAC,oBAAoB,KAC7G,EACE,uCACA,sBACD;OAEP,CAAA;MACF,kBAAC,GAAD;OACE,OAAO,EAAG,kCAAkC,gBAAgB;OAC5D,OAAO,IAAI,EAAQ,kBAAkB,gBAAgB;OACrD,MAAM,kBAAC,IAAD,EAAiB,MAAM,IAAM,CAAA;OACnC,aAAa,GAAG,EAAQ,kBAAkB,GAAG,EAAG,6BAA6B,UAAU;OACvF,CAAA;MACW;;IAEf,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,OAAO,EAAG,kCAAkC,gBAAgB;gBAE5D,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD;QAAqB,OAAM;QAAO,QAAQ;kBACxC,kBAAC,GAAD;SAAW,MAAM;mBAAjB;UACE,kBAAC,GAAD;WACE,iBAAgB;WAChB,QAAO;WACP,CAAA;UACF,kBAAC,GAAD;WACE,SAAQ;WACR,QAAO;WACP,UAAU;WACV,CAAA;UACF,kBAAC,GAAD;WAAO,QAAO;WAA0B,UAAU;WAAM,CAAA;UACxD,kBAAC,GAAD,EACE,cAAc;WACZ,iBAAiB;WACjB,QAAQ;WACR,cAAc;WACf,EACD,CAAA;UACF,kBAAC,GAAD;WACE,MAAK;WACL,SAAQ;WACR,QAAQ,EAAY;WACpB,aAAa;WACb,KAAK;WACL,CAAA;UACF,kBAAC,GAAD;WACE,MAAK;WACL,SAAQ;WACR,QAAQ,EAAY;WACpB,aAAa;WACb,KAAK;WACL,CAAA;UACQ;;QACQ,CAAA;OAClB,CAAA;MACM,CAAA,EAEd,kBAAC,GAAD;MACE,OAAO,EACL,6BACA,8BACD;gBAEA,EAAQ,QAAQ,SAAS,IACxB,kBAAC,OAAD;OAAK,WAAU;iBACZ,EAAQ,QAAQ,KAEb,MAEA,kBAAC,OAAD;QAEE,WAAU;kBAEV,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAY;UACX,CAAA,EACJ,kBAAC,KAAD;UAAG,WAAU;oBAAb;WACG,EAAY;WAAY;WACxB,EAAG,2BAA2B,QAAQ;WACrC;YACA,EAAA,CAAA,EACN,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,KAAD;WAAG,WAAU;qBAAb,CAA6B,KACzB,EAAY,aAAa,gBAAgB,CACzC;cACJ,kBAAC,KAAD;WAAG,WAAU;qBAAb;YACG,EAAG,yBAAyB,MAAM;YAAC;YACnC,EAAY,WAAW,gBAAgB;YACtC;aACA;YACF;;QACF,EAvBC,EAAY,cAuBb,CAET;OACG,CAAA,GAEN,kBAAC,GAAD;OACE,MAAM,kBAAC,GAAD,EAAW,MAAM,IAAM,CAAA;OAC7B,OAAO,EACL,oCACA,yBACD;OACD,aAAa,EACX,0CACA,yEACD;OACD,CAAA;MAEQ,CAAA,CACV;;IAEN,kBAAC,GAAD;KACE,OAAO,EAAG,iCAAiC,eAAe;eAE1D,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAqB,OAAM;OAAO,QAAQ;iBACxC,kBAAC,GAAD;QAAU,MAAM;kBAAhB;SACE,kBAAC,GAAD;UACE,iBAAgB;UAChB,QAAO;UACP,CAAA;SACF,kBAAC,GAAD;UACE,SAAQ;UACR,QAAO;UACP,UAAU;UACV,CAAA;SACF,kBAAC,GAAD;UAAO,QAAO;UAA0B,UAAU;UAAM,CAAA;SACxD,kBAAC,GAAD,EACE,cAAc;UACZ,iBAAiB;UACjB,QAAQ;UACR,cAAc;UACf,EACD,CAAA;SACF,kBAAC,IAAD;UACE,SAAQ;UACR,MAAM,EAAY;UAClB,QAAQ;WAAC;WAAG;WAAG;WAAG;WAAE;UACpB,CAAA;SACO;;OACS,CAAA;MAClB,CAAA;KACM,CAAA;IAEd,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD;MACE,OAAO,EAAG,iCAAiC,eAAe;gBAE1D,kBAAC,GAAD;OACE,MAAM;OACN,UAAS;OACT,SAAS;QACP;SACE,KAAK;SACL,QAAQ,EAAG,iCAAiC,cAAc;SAC1D,SAAS,MACP,EAAK,aAAa,QAClB,EAAK,YACL,EAAG,4BAA4B,UAAU;SAC5C;QACD;SACE,KAAK;SACL,QAAQ,EAAG,2BAA2B,QAAQ;SAC9C,SAAS,MAAS,IAAI,EAAK,YAAY,gBAAgB;SACxD;QACD;SACE,KAAK;SACL,QAAQ,EAAG,yBAAyB,MAAM;SAC1C,SAAS,MAAS,IAAI,EAAK,UAAU,gBAAgB;SACtD;QACD;SACE,KAAK;SACL,QAAQ,EAAG,4BAA4B,SAAS;SAChD,SAAS,MACP,kBAAC,GAAD;UAAa,QAAQ,EAAK;UAAQ,MAAK;UAAQ,CAAA;SAElD;QACF;OACD,CAAA;MACU,CAAA,EAEd,kBAAC,GAAD;MACE,OAAO,EAAG,mCAAmC,iBAAiB;gBAE9D,kBAAC,GAAD;OACE,MAAM;OACN,UAAS;OACT,SAAS;QACP;SACE,KAAK;SACL,QAAQ,EAAG,4BAA4B,SAAS;SAChD,SAAS,MAAW,EAAO;SAC5B;QACD;SACE,KAAK;SACL,QAAQ,EAAG,+BAA+B,aAAa;SACvD,SAAS,MAAW,IAAI,EAAO,UAAU,gBAAgB;SAC1D;QACD;SACE,KAAK;SACL,QAAQ,EAAG,4BAA4B,SAAS;SAChD,SAAS,MACP,kBAAC,GAAD;UAAa,QAAQ,EAAO;UAAQ,MAAK;UAAQ,CAAA;SAEpD;QACF;OACD,CAAA;MACU,CAAA,CACV;;IACL,EAAA,CAAA,GAEH,kBAAC,GAAD;IACE,MAAM,kBAAC,GAAD,EAAY,MAAM,IAAM,CAAA;IAC9B,OAAO,EAAG,iCAAiC,sBAAsB;IACjE,aAAa,EACX,uCACA,0FACD;IACD,CAAA;GAEO;MApjBX,kBAAC,GAAD;EACE,OAAO,EAAG,2BAA2B,UAAU;EAC/C,aAAa,EACX,iCACA,kFACD;YAED,kBAAC,GAAD;GACE,MAAM,kBAAC,GAAD;IAAW,MAAM;IAAI,WAAU;IAA0B,CAAA;GAC/D,OAAO,EACL,oCACA,yBACD;GACD,aAAa,EACX,mCACA,qGACD;GACD,CAAA;EACS,CAAA"}
@@ -1584,17 +1584,11 @@ e`
1584
1584
  getBillingAccount(id: $id) {
1585
1585
  ...BillingAccountFields
1586
1586
  }
1587
- }
1588
- ${d}`, e`
1589
- query GetBillingAccountsByOrg {
1590
- getBillingAccountsByOrg {
1591
- ...BillingAccountFields
1592
- }
1593
1587
  }
1594
1588
  ${d}`;
1595
1589
  var bt = e`
1596
- query MyBillingAccounts {
1597
- myBillingAccounts {
1590
+ query GetBillingAccountsByOrg {
1591
+ getBillingAccountsByOrg {
1598
1592
  ...BillingAccountFields
1599
1593
  }
1600
1594
  }
@@ -1606,6 +1600,13 @@ function xt(e) {
1606
1600
  };
1607
1601
  return t.useQuery(bt, r);
1608
1602
  }
1603
+ e`
1604
+ query MyBillingAccounts {
1605
+ myBillingAccounts {
1606
+ ...BillingAccountFields
1607
+ }
1608
+ }
1609
+ ${d}`;
1609
1610
  var St = e`
1610
1611
  query GetMyDeveloperProfile {
1611
1612
  myDeveloperProfile {
@@ -2124,6 +2125,6 @@ function Wt(e) {
2124
2125
  return t.useMutation(Ut, r);
2125
2126
  }
2126
2127
  //#endregion
2127
- export { a as AppInstallationFieldsFragmentDoc, r as ApplicationFieldsFragmentDoc, ee as ApplicationScopeFieldsFragmentDoc, i as ApplicationVersionFieldsFragmentDoc, O as ApproveApplicationDocument, te as AuditLogFieldsFragmentDoc, o as AuthAppFieldsFragmentDoc, d as BillingAccountFieldsFragmentDoc, et as CancelInvitationDocument, w as CreateApplicationDocument, A as CreateApplicationVersionDocument, U as CreateAuthAppDocument, vt as CreateBillingAccountDocument, Ke as CreateOrganizationDocument, Lt as CreateWebhookDocument, V as CurrentUserAppsDocument, J as CurrentUserDelegationsDocument, Y as CurrentUserGrantedDelegationsDocument, G as DeactivateAppDocument, s as DelegationFieldsFragmentDoc, E as DeleteApplicationDocument, Xe as DeleteOrganizationDocument, Vt as DeleteWebhookDocument, M as DeprecateApplicationVersionDocument, f as DeveloperProfileFieldsFragmentDoc, _ as DevportalWebhookFieldsFragmentDoc, R as GenerateApiKeyDocument, ne as GetAnalyticsDashboardOptionsDocument, y as GetApplicationAnalyticsDashboardDocument, C as GetApplicationAnalyticsDocument, wt as GetApplicationAuditLogsDocument, x as GetApplicationDocument, I as GetApplicationForReviewDocument, S as GetApplicationVersionsDocument, b as GetApplicationsDocument, H as GetAuthAppDocument, At as GetDeveloperPortalSettingsOverviewDocument, q as GetDevportalDashboardBootstrapDocument, St as GetMyDeveloperProfileDocument, Q as GetMyOrganizationsDocument, Be as GetOrganizationDocument, We as GetOrganizationInvitationsDocument, He as GetOrganizationMembersDocument, Re as GetOrganizationsDocument, Ot as GetRevenueDashboardDataDocument, Ft as GetWebhookDetailDocument, $ as GetWebhookDocument, Mt as GetWebhooksDocument, F as GetWorkspaceInstallationDocument, X as GrantDelegationDocument, N as InstallApplicationDocument, Qe as InviteMemberDocument, gt as LinkDevOrgBillingAccountDocument, L as MyApiKeysDocument, bt as MyBillingAccountsDocument, u as OrgInvitationFieldsFragmentDoc, l as OrgMemberFieldsFragmentDoc, c as OrganizationFieldsFragmentDoc, h as PaymentMethodFieldsFragmentDoc, m as PayoutFieldsFragmentDoc, j as PublishApplicationVersionDocument, ut as ReactivateMemberDocument, k as RejectApplicationDocument, ot as RemoveMemberDocument, mt as RequestOrgVerificationDocument, nt as ResendInvitationDocument, g as RevenueAnalyticsFieldsFragmentDoc, z as RevokeApiKeyAuthDocument, Z as RevokeDelegationDocument, B as RotateApiKeyAuthDocument, K as RotateAppSecretDocument, p as SaleFieldsFragmentDoc, D as SubmitApplicationDocument, ct as SuspendMemberDocument, Ut as TestWebhookDocument, ft as TransferOwnershipDocument, P as UninstallApplicationDocument, T as UpdateApplicationDocument, W as UpdateAuthAppDocument, Et as UpdateDeveloperProfileDocument, it as UpdateMemberRoleDocument, Je as UpdateOrganizationDocument, zt as UpdateWebhookDocument, v as WebhookDeliveryFieldsFragmentDoc, pe as useApproveApplicationMutation, tt as useCancelInvitationMutation, le as useCreateApplicationMutation, he as useCreateApplicationVersionMutation, Oe as useCreateAuthAppMutation, yt as useCreateBillingAccountMutation, qe as useCreateOrganizationMutation, Rt as useCreateWebhookMutation, Ee as useCurrentUserAppsQuery, Ne as useCurrentUserDelegationsQuery, Pe as useCurrentUserGrantedDelegationsQuery, Ae as useDeactivateAppMutation, de as useDeleteApplicationMutation, Ze as useDeleteOrganizationMutation, Ht as useDeleteWebhookMutation, _e as useDeprecateApplicationVersionMutation, Ce as useGenerateApiKeyMutation, re as useGetAnalyticsDashboardOptionsQuery, ie as useGetApplicationAnalyticsDashboardQuery, ce as useGetApplicationAnalyticsQuery, Tt as useGetApplicationAuditLogsQuery, xe as useGetApplicationForReviewQuery, oe as useGetApplicationQuery, se as useGetApplicationVersionsQuery, ae as useGetApplicationsQuery, De as useGetAuthAppQuery, jt as useGetDeveloperPortalSettingsOverviewQuery, Me as useGetDevportalDashboardBootstrapQuery, Ct as useGetMyDeveloperProfileQuery, Le as useGetMyOrganizationsQuery, Ge as useGetOrganizationInvitationsQuery, Ue as useGetOrganizationMembersQuery, Ve as useGetOrganizationQuery, ze as useGetOrganizationsQuery, kt as useGetRevenueDashboardDataQuery, It as useGetWebhookDetailQuery, Pt as useGetWebhookQuery, Nt as useGetWebhooksQuery, be as useGetWorkspaceInstallationQuery, Fe as useGrantDelegationMutation, ve as useInstallApplicationMutation, $e as useInviteMemberMutation, _t as useLinkDevOrgBillingAccountMutation, Se as useMyApiKeysQuery, xt as useMyBillingAccountsQuery, ge as usePublishApplicationVersionMutation, dt as useReactivateMemberMutation, me as useRejectApplicationMutation, st as useRemoveMemberMutation, ht as useRequestOrgVerificationMutation, rt as useResendInvitationMutation, we as useRevokeApiKeyAuthMutation, Ie as useRevokeDelegationMutation, Te as useRotateApiKeyAuthMutation, je as useRotateAppSecretMutation, fe as useSubmitApplicationMutation, lt as useSuspendMemberMutation, Wt as useTestWebhookMutation, pt as useTransferOwnershipMutation, ye as useUninstallApplicationMutation, ue as useUpdateApplicationMutation, ke as useUpdateAuthAppMutation, Dt as useUpdateDeveloperProfileMutation, at as useUpdateMemberRoleMutation, Ye as useUpdateOrganizationMutation, Bt as useUpdateWebhookMutation };
2128
+ export { a as AppInstallationFieldsFragmentDoc, r as ApplicationFieldsFragmentDoc, ee as ApplicationScopeFieldsFragmentDoc, i as ApplicationVersionFieldsFragmentDoc, O as ApproveApplicationDocument, te as AuditLogFieldsFragmentDoc, o as AuthAppFieldsFragmentDoc, d as BillingAccountFieldsFragmentDoc, et as CancelInvitationDocument, w as CreateApplicationDocument, A as CreateApplicationVersionDocument, U as CreateAuthAppDocument, vt as CreateBillingAccountDocument, Ke as CreateOrganizationDocument, Lt as CreateWebhookDocument, V as CurrentUserAppsDocument, J as CurrentUserDelegationsDocument, Y as CurrentUserGrantedDelegationsDocument, G as DeactivateAppDocument, s as DelegationFieldsFragmentDoc, E as DeleteApplicationDocument, Xe as DeleteOrganizationDocument, Vt as DeleteWebhookDocument, M as DeprecateApplicationVersionDocument, f as DeveloperProfileFieldsFragmentDoc, _ as DevportalWebhookFieldsFragmentDoc, R as GenerateApiKeyDocument, ne as GetAnalyticsDashboardOptionsDocument, y as GetApplicationAnalyticsDashboardDocument, C as GetApplicationAnalyticsDocument, wt as GetApplicationAuditLogsDocument, x as GetApplicationDocument, I as GetApplicationForReviewDocument, S as GetApplicationVersionsDocument, b as GetApplicationsDocument, H as GetAuthAppDocument, bt as GetBillingAccountsByOrgDocument, At as GetDeveloperPortalSettingsOverviewDocument, q as GetDevportalDashboardBootstrapDocument, St as GetMyDeveloperProfileDocument, Q as GetMyOrganizationsDocument, Be as GetOrganizationDocument, We as GetOrganizationInvitationsDocument, He as GetOrganizationMembersDocument, Re as GetOrganizationsDocument, Ot as GetRevenueDashboardDataDocument, Ft as GetWebhookDetailDocument, $ as GetWebhookDocument, Mt as GetWebhooksDocument, F as GetWorkspaceInstallationDocument, X as GrantDelegationDocument, N as InstallApplicationDocument, Qe as InviteMemberDocument, gt as LinkDevOrgBillingAccountDocument, L as MyApiKeysDocument, u as OrgInvitationFieldsFragmentDoc, l as OrgMemberFieldsFragmentDoc, c as OrganizationFieldsFragmentDoc, h as PaymentMethodFieldsFragmentDoc, m as PayoutFieldsFragmentDoc, j as PublishApplicationVersionDocument, ut as ReactivateMemberDocument, k as RejectApplicationDocument, ot as RemoveMemberDocument, mt as RequestOrgVerificationDocument, nt as ResendInvitationDocument, g as RevenueAnalyticsFieldsFragmentDoc, z as RevokeApiKeyAuthDocument, Z as RevokeDelegationDocument, B as RotateApiKeyAuthDocument, K as RotateAppSecretDocument, p as SaleFieldsFragmentDoc, D as SubmitApplicationDocument, ct as SuspendMemberDocument, Ut as TestWebhookDocument, ft as TransferOwnershipDocument, P as UninstallApplicationDocument, T as UpdateApplicationDocument, W as UpdateAuthAppDocument, Et as UpdateDeveloperProfileDocument, it as UpdateMemberRoleDocument, Je as UpdateOrganizationDocument, zt as UpdateWebhookDocument, v as WebhookDeliveryFieldsFragmentDoc, pe as useApproveApplicationMutation, tt as useCancelInvitationMutation, le as useCreateApplicationMutation, he as useCreateApplicationVersionMutation, Oe as useCreateAuthAppMutation, yt as useCreateBillingAccountMutation, qe as useCreateOrganizationMutation, Rt as useCreateWebhookMutation, Ee as useCurrentUserAppsQuery, Ne as useCurrentUserDelegationsQuery, Pe as useCurrentUserGrantedDelegationsQuery, Ae as useDeactivateAppMutation, de as useDeleteApplicationMutation, Ze as useDeleteOrganizationMutation, Ht as useDeleteWebhookMutation, _e as useDeprecateApplicationVersionMutation, Ce as useGenerateApiKeyMutation, re as useGetAnalyticsDashboardOptionsQuery, ie as useGetApplicationAnalyticsDashboardQuery, ce as useGetApplicationAnalyticsQuery, Tt as useGetApplicationAuditLogsQuery, xe as useGetApplicationForReviewQuery, oe as useGetApplicationQuery, se as useGetApplicationVersionsQuery, ae as useGetApplicationsQuery, De as useGetAuthAppQuery, xt as useGetBillingAccountsByOrgQuery, jt as useGetDeveloperPortalSettingsOverviewQuery, Me as useGetDevportalDashboardBootstrapQuery, Ct as useGetMyDeveloperProfileQuery, Le as useGetMyOrganizationsQuery, Ge as useGetOrganizationInvitationsQuery, Ue as useGetOrganizationMembersQuery, Ve as useGetOrganizationQuery, ze as useGetOrganizationsQuery, kt as useGetRevenueDashboardDataQuery, It as useGetWebhookDetailQuery, Pt as useGetWebhookQuery, Nt as useGetWebhooksQuery, be as useGetWorkspaceInstallationQuery, Fe as useGrantDelegationMutation, ve as useInstallApplicationMutation, $e as useInviteMemberMutation, _t as useLinkDevOrgBillingAccountMutation, Se as useMyApiKeysQuery, ge as usePublishApplicationVersionMutation, dt as useReactivateMemberMutation, me as useRejectApplicationMutation, st as useRemoveMemberMutation, ht as useRequestOrgVerificationMutation, rt as useResendInvitationMutation, we as useRevokeApiKeyAuthMutation, Ie as useRevokeDelegationMutation, Te as useRotateApiKeyAuthMutation, je as useRotateAppSecretMutation, fe as useSubmitApplicationMutation, lt as useSuspendMemberMutation, Wt as useTestWebhookMutation, pt as useTransferOwnershipMutation, ye as useUninstallApplicationMutation, ue as useUpdateApplicationMutation, ke as useUpdateAuthAppMutation, Dt as useUpdateDeveloperProfileMutation, at as useUpdateMemberRoleMutation, Ye as useUpdateOrganizationMutation, Bt as useUpdateWebhookMutation };
2128
2129
 
2129
2130
  //# sourceMappingURL=global-operations.js.map