@burdenoff/microfe-devportal 2026.914.1 → 2026.914.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devportal/DevportalRoutes.d.ts.map +1 -1
- package/dist/devportal/DevportalRoutes.js +130 -110
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/components/SectionNav.d.ts +10 -1
- package/dist/devportal/components/SectionNav.d.ts.map +1 -1
- package/dist/devportal/components/SectionNav.js +60 -42
- package/dist/devportal/components/SectionNav.js.map +1 -1
- package/dist/devportal/hooks/useIsSellerSection.d.ts +13 -0
- package/dist/devportal/hooks/useIsSellerSection.d.ts.map +1 -0
- package/dist/devportal/hooks/useIsSellerSection.js +15 -0
- package/dist/devportal/hooks/useIsSellerSection.js.map +1 -0
- package/dist/devportal/pages/CreateOrganizationPage.d.ts.map +1 -1
- package/dist/devportal/pages/CreateOrganizationPage.js +107 -106
- package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.js +349 -336
- package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +291 -290
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.js +102 -101
- package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js +210 -209
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.js +14 -22
- package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
- package/dist/generated/global-operations.d.ts +102 -12
- package/dist/generated/global-operations.d.ts.map +1 -1
- package/dist/generated/global-operations.js +107 -92
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +2963 -242
- package/dist/generated/global-types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,125 +1,126 @@
|
|
|
1
1
|
import { useDevportal as e } from "../providers/DevportalProvider.js";
|
|
2
2
|
import { useTr as t } from "../utils/i18n.js";
|
|
3
3
|
import { EmptyState as n } from "../components/EmptyState.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
4
|
+
import { orgSectionPath as r, useIsSellerSection as i } from "../hooks/useIsSellerSection.js";
|
|
5
|
+
import { useGetMyOrganizationsQuery as a } from "../../generated/global-operations.js";
|
|
6
|
+
import { getErrorMessage as o } from "../hooks/useGraphQL.js";
|
|
7
|
+
import { PageLayout as s } from "../components/PageLayout.js";
|
|
8
|
+
import { StatusBadge as c, VerifiedBadge as l } from "../components/StatusBadge.js";
|
|
9
|
+
import { PermissionGuard as u } from "../components/PermissionGuard.js";
|
|
9
10
|
import "../components/index.js";
|
|
10
11
|
import "../hooks/index.js";
|
|
11
|
-
import { AlertCircle as
|
|
12
|
-
import { jsx as
|
|
13
|
-
import { EmphasisPanel as
|
|
12
|
+
import { AlertCircle as d, AppWindow as f, Building2 as p, CheckCircle as m, DollarSign as h, Loader2 as g, Plus as _, Users as v } from "lucide-react";
|
|
13
|
+
import { jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
14
|
+
import { EmphasisPanel as x, GlassCard as S } from "@burdenoff/fe-libs/ui";
|
|
14
15
|
//#region src/devportal/pages/OrganizationsPage.tsx
|
|
15
|
-
var
|
|
16
|
-
let { navigate:
|
|
17
|
-
|
|
18
|
-
};
|
|
19
|
-
return
|
|
20
|
-
title:
|
|
21
|
-
description:
|
|
22
|
-
children: /* @__PURE__ */
|
|
16
|
+
var C = () => {
|
|
17
|
+
let { navigate: c, basePath: l } = e(), f = t(), p = i(), { data: m, loading: h, error: v, refetch: C } = a({ fetchPolicy: "cache-and-network" }), T = (m?.myDeveloperOrganizations ?? []).filter((e) => p ? e.kind === "PHYSICAL" : e.kind !== "PHYSICAL"), E = (e) => {
|
|
18
|
+
c?.(`${l}${e}`);
|
|
19
|
+
}, D = r(p, "new"), O = (e) => r(p, e), k = p ? f("devportal.sellerOrganizations", "Seller Organizations") : f("devportal.developerOrganizations", "Developer Organizations"), A = p ? f("devportal.manageYourSellerOrgs", "Manage the organizations you sell physical goods under") : f("devportal.manageYourDevTeams", "Manage your development teams");
|
|
20
|
+
return h && !m ? /* @__PURE__ */ y(s, {
|
|
21
|
+
title: k,
|
|
22
|
+
description: A,
|
|
23
|
+
children: /* @__PURE__ */ b("div", {
|
|
23
24
|
className: "flex items-center justify-center py-12",
|
|
24
|
-
children: [/* @__PURE__ */
|
|
25
|
+
children: [/* @__PURE__ */ y(g, { className: "h-8 w-8 animate-spin text-text-secondary" }), /* @__PURE__ */ y("span", {
|
|
25
26
|
className: "ml-2 text-text-secondary",
|
|
26
|
-
children:
|
|
27
|
+
children: f("devportal.loadingOrganizations", "Loading organizations...")
|
|
27
28
|
})]
|
|
28
29
|
})
|
|
29
|
-
}) :
|
|
30
|
-
title:
|
|
31
|
-
description:
|
|
32
|
-
children: /* @__PURE__ */
|
|
30
|
+
}) : v ? /* @__PURE__ */ y(s, {
|
|
31
|
+
title: k,
|
|
32
|
+
description: A,
|
|
33
|
+
children: /* @__PURE__ */ b("div", {
|
|
33
34
|
className: "rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center",
|
|
34
35
|
children: [
|
|
35
|
-
/* @__PURE__ */
|
|
36
|
-
/* @__PURE__ */
|
|
36
|
+
/* @__PURE__ */ y(d, { className: "mx-auto h-8 w-8 text-status-error-text" }),
|
|
37
|
+
/* @__PURE__ */ y("h3", {
|
|
37
38
|
className: "mt-2 font-medium text-status-error-text",
|
|
38
|
-
children:
|
|
39
|
+
children: f("devportal.failedToLoadOrganizations", "Failed to load organizations")
|
|
39
40
|
}),
|
|
40
|
-
/* @__PURE__ */
|
|
41
|
+
/* @__PURE__ */ y("p", {
|
|
41
42
|
className: "mt-1 text-sm text-text-secondary",
|
|
42
|
-
children:
|
|
43
|
+
children: o(v)
|
|
43
44
|
}),
|
|
44
|
-
/* @__PURE__ */
|
|
45
|
-
onClick: () =>
|
|
45
|
+
/* @__PURE__ */ y("button", {
|
|
46
|
+
onClick: () => C(),
|
|
46
47
|
className: "mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
47
|
-
children:
|
|
48
|
+
children: f("devportal.tryAgain", "Try Again")
|
|
48
49
|
})
|
|
49
50
|
]
|
|
50
51
|
})
|
|
51
|
-
}) : /* @__PURE__ */
|
|
52
|
+
}) : /* @__PURE__ */ y(u, {
|
|
52
53
|
authOnly: !0,
|
|
53
|
-
children: /* @__PURE__ */
|
|
54
|
-
title:
|
|
55
|
-
description:
|
|
56
|
-
purpose:
|
|
57
|
-
actions: /* @__PURE__ */
|
|
58
|
-
onClick: () =>
|
|
54
|
+
children: /* @__PURE__ */ b(s, {
|
|
55
|
+
title: k,
|
|
56
|
+
description: A,
|
|
57
|
+
purpose: p ? f("devportal.sellerOrganizationsPurpose", "A seller organization owns your physical listings, orders, and revenue. It's created automatically the first time you list an item, or you can create one here.") : f("devportal.organizationsPurpose", "An organization is the team that owns your apps, members, and revenue. Create one so collaborators can share access to the same applications, billing, and store presence instead of working in isolation."),
|
|
58
|
+
actions: /* @__PURE__ */ b("button", {
|
|
59
|
+
onClick: () => E(D),
|
|
59
60
|
className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors",
|
|
60
|
-
children: [/* @__PURE__ */ _
|
|
61
|
+
children: [/* @__PURE__ */ y(_, { size: 16 }), f("devportal.createOrganization", "Create Organization")]
|
|
61
62
|
}),
|
|
62
|
-
children: [
|
|
63
|
+
children: [T.length > 0 && /* @__PURE__ */ y(x, {
|
|
63
64
|
className: "mb-6",
|
|
64
|
-
children: /* @__PURE__ */
|
|
65
|
+
children: /* @__PURE__ */ b("div", {
|
|
65
66
|
className: "grid grid-cols-2 gap-4 sm:grid-cols-3",
|
|
66
67
|
children: [
|
|
67
|
-
/* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ b(S, {
|
|
68
69
|
treatment: "metric",
|
|
69
70
|
className: "p-4",
|
|
70
|
-
children: [/* @__PURE__ */
|
|
71
|
+
children: [/* @__PURE__ */ y("p", {
|
|
71
72
|
className: "text-sm text-text-secondary",
|
|
72
|
-
children:
|
|
73
|
-
}), /* @__PURE__ */
|
|
73
|
+
children: f("devportal.organizations", "Organizations")
|
|
74
|
+
}), /* @__PURE__ */ y("p", {
|
|
74
75
|
className: "mt-1 text-2xl font-semibold tabular-nums",
|
|
75
|
-
children:
|
|
76
|
+
children: T.length
|
|
76
77
|
})]
|
|
77
78
|
}),
|
|
78
|
-
/* @__PURE__ */
|
|
79
|
+
/* @__PURE__ */ b(S, {
|
|
79
80
|
treatment: "metric",
|
|
80
81
|
className: "p-4",
|
|
81
|
-
children: [/* @__PURE__ */
|
|
82
|
+
children: [/* @__PURE__ */ y("p", {
|
|
82
83
|
className: "text-sm text-text-secondary",
|
|
83
|
-
children:
|
|
84
|
-
}), /* @__PURE__ */
|
|
84
|
+
children: f("devportal.totalApps", "Total Apps")
|
|
85
|
+
}), /* @__PURE__ */ y("p", {
|
|
85
86
|
className: "mt-1 text-2xl font-semibold tabular-nums",
|
|
86
|
-
children:
|
|
87
|
+
children: T.reduce((e, t) => e + (t.totalApps ?? 0), 0)
|
|
87
88
|
})]
|
|
88
89
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
90
|
+
/* @__PURE__ */ b(S, {
|
|
90
91
|
treatment: "metric",
|
|
91
92
|
className: "p-4",
|
|
92
|
-
children: [/* @__PURE__ */
|
|
93
|
+
children: [/* @__PURE__ */ y("p", {
|
|
93
94
|
className: "text-sm text-text-secondary",
|
|
94
|
-
children:
|
|
95
|
-
}), /* @__PURE__ */
|
|
95
|
+
children: f("devportal.activeInstalls", "Active Installs")
|
|
96
|
+
}), /* @__PURE__ */ y("p", {
|
|
96
97
|
className: "mt-1 text-2xl font-semibold tabular-nums",
|
|
97
|
-
children:
|
|
98
|
+
children: T.reduce((e, t) => e + (t.activeInstalls ?? 0), 0).toLocaleString()
|
|
98
99
|
})]
|
|
99
100
|
})
|
|
100
101
|
]
|
|
101
102
|
})
|
|
102
|
-
}),
|
|
103
|
+
}), T.length > 0 ? /* @__PURE__ */ y("div", {
|
|
103
104
|
className: "grid gap-6",
|
|
104
|
-
children:
|
|
105
|
+
children: T.map((e) => /* @__PURE__ */ y(w, {
|
|
105
106
|
org: e,
|
|
106
|
-
onClick: () =>
|
|
107
|
+
onClick: () => E(O(e.id))
|
|
107
108
|
}, e.id))
|
|
108
|
-
}) : /* @__PURE__ */
|
|
109
|
+
}) : /* @__PURE__ */ y(n, {
|
|
109
110
|
illustration: "empty-people",
|
|
110
|
-
title:
|
|
111
|
-
description:
|
|
112
|
-
action: /* @__PURE__ */
|
|
113
|
-
onClick: () =>
|
|
111
|
+
title: p ? f("devportal.noSellerOrganizationsYet", "No seller organizations yet") : f("devportal.noOrganizationsYet", "No organizations yet"),
|
|
112
|
+
description: p ? f("devportal.createSellerOrgToSell", "Create a seller organization to start selling physical products, or list your first item and one will be set up for you") : f("devportal.createOrgToCollaborate", "Create an organization to collaborate with your team and manage apps together"),
|
|
113
|
+
action: /* @__PURE__ */ b("button", {
|
|
114
|
+
onClick: () => E(D),
|
|
114
115
|
className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90",
|
|
115
|
-
children: [/* @__PURE__ */ _
|
|
116
|
+
children: [/* @__PURE__ */ y(_, { size: 16 }), f("devportal.createOrganization", "Create Organization")]
|
|
116
117
|
})
|
|
117
118
|
})]
|
|
118
119
|
})
|
|
119
120
|
});
|
|
120
|
-
},
|
|
121
|
+
}, w = ({ org: e, onClick: n }) => {
|
|
121
122
|
let r = t();
|
|
122
|
-
return /* @__PURE__ */
|
|
123
|
+
return /* @__PURE__ */ b("div", {
|
|
123
124
|
role: "button",
|
|
124
125
|
tabIndex: 0,
|
|
125
126
|
onClick: n,
|
|
@@ -127,71 +128,71 @@ var x = () => {
|
|
|
127
128
|
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), n());
|
|
128
129
|
},
|
|
129
130
|
className: "cursor-pointer rounded-card border border-border-seam bg-bg-surface p-6 shadow-[var(--shadow-pop)] transition-[box-shadow,border-color] hover:shadow-[var(--shadow-pop-hover)] hover:border-border-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
130
|
-
children: [/* @__PURE__ */
|
|
131
|
+
children: [/* @__PURE__ */ b("div", {
|
|
131
132
|
className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
|
|
132
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ b("div", {
|
|
133
134
|
className: "flex items-start gap-4",
|
|
134
|
-
children: [e.logoUrl ? /* @__PURE__ */
|
|
135
|
+
children: [e.logoUrl ? /* @__PURE__ */ y("img", {
|
|
135
136
|
src: e.logoUrl,
|
|
136
137
|
alt: e.name,
|
|
137
138
|
className: "h-16 w-16 rounded-lg object-cover"
|
|
138
|
-
}) : /* @__PURE__ */
|
|
139
|
+
}) : /* @__PURE__ */ y("div", {
|
|
139
140
|
className: "flex h-16 w-16 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary",
|
|
140
|
-
children: /* @__PURE__ */
|
|
141
|
-
}), /* @__PURE__ */
|
|
142
|
-
/* @__PURE__ */
|
|
141
|
+
children: /* @__PURE__ */ y(p, { size: 32 })
|
|
142
|
+
}), /* @__PURE__ */ b("div", { children: [
|
|
143
|
+
/* @__PURE__ */ b("div", {
|
|
143
144
|
className: "flex items-center gap-2 flex-wrap",
|
|
144
145
|
children: [
|
|
145
|
-
/* @__PURE__ */
|
|
146
|
+
/* @__PURE__ */ y("h3", {
|
|
146
147
|
className: "text-lg font-semibold",
|
|
147
148
|
children: e.name
|
|
148
149
|
}),
|
|
149
|
-
e.isVerified && /* @__PURE__ */
|
|
150
|
-
e.isCertified && /* @__PURE__ */
|
|
150
|
+
e.isVerified && /* @__PURE__ */ y(l, { verified: !0 }),
|
|
151
|
+
e.isCertified && /* @__PURE__ */ b("span", {
|
|
151
152
|
className: "inline-flex items-center gap-1 rounded-full bg-status-info-bg-subtle px-2 py-0.5 text-xs font-medium text-status-info-text",
|
|
152
153
|
children: [
|
|
153
|
-
/* @__PURE__ */
|
|
154
|
+
/* @__PURE__ */ y(m, { size: 12 }),
|
|
154
155
|
" ",
|
|
155
156
|
r("devportal.certified", "Certified")
|
|
156
157
|
]
|
|
157
158
|
})
|
|
158
159
|
]
|
|
159
160
|
}),
|
|
160
|
-
e.description && /* @__PURE__ */
|
|
161
|
+
e.description && /* @__PURE__ */ y("p", {
|
|
161
162
|
className: "mt-1 text-sm text-text-secondary",
|
|
162
163
|
children: e.description
|
|
163
164
|
}),
|
|
164
|
-
/* @__PURE__ */
|
|
165
|
+
/* @__PURE__ */ b("div", {
|
|
165
166
|
className: "mt-2 flex flex-wrap items-center gap-2",
|
|
166
|
-
children: [/* @__PURE__ */
|
|
167
|
+
children: [/* @__PURE__ */ y(c, {
|
|
167
168
|
status: e.tier,
|
|
168
169
|
type: "tier"
|
|
169
|
-
}), e.partnerTier && /* @__PURE__ */
|
|
170
|
+
}), e.partnerTier && /* @__PURE__ */ y(c, {
|
|
170
171
|
status: e.partnerTier,
|
|
171
172
|
type: "partner"
|
|
172
173
|
})]
|
|
173
174
|
})
|
|
174
175
|
] })]
|
|
175
|
-
}), /* @__PURE__ */
|
|
176
|
+
}), /* @__PURE__ */ b("div", {
|
|
176
177
|
className: "flex flex-wrap gap-6 text-sm",
|
|
177
178
|
children: [
|
|
178
|
-
/* @__PURE__ */
|
|
179
|
+
/* @__PURE__ */ b("div", {
|
|
179
180
|
className: "flex items-center gap-2",
|
|
180
|
-
children: [/* @__PURE__ */
|
|
181
|
+
children: [/* @__PURE__ */ y(v, {
|
|
181
182
|
size: 16,
|
|
182
183
|
className: "text-text-secondary"
|
|
183
|
-
}), /* @__PURE__ */
|
|
184
|
+
}), /* @__PURE__ */ b("span", { children: [
|
|
184
185
|
e.members?.length || 0,
|
|
185
186
|
" ",
|
|
186
187
|
r("devportal.membersLower", "members")
|
|
187
188
|
] })]
|
|
188
189
|
}),
|
|
189
|
-
/* @__PURE__ */
|
|
190
|
+
/* @__PURE__ */ b("div", {
|
|
190
191
|
className: "flex items-center gap-2",
|
|
191
|
-
children: [/* @__PURE__ */
|
|
192
|
+
children: [/* @__PURE__ */ y(f, {
|
|
192
193
|
size: 16,
|
|
193
194
|
className: "text-text-secondary"
|
|
194
|
-
}), /* @__PURE__ */
|
|
195
|
+
}), /* @__PURE__ */ b("span", { children: [
|
|
195
196
|
e.publishedApps,
|
|
196
197
|
" / ",
|
|
197
198
|
e.totalApps,
|
|
@@ -199,43 +200,43 @@ var x = () => {
|
|
|
199
200
|
r("devportal.appsLower", "apps")
|
|
200
201
|
] })]
|
|
201
202
|
}),
|
|
202
|
-
/* @__PURE__ */
|
|
203
|
+
/* @__PURE__ */ b("div", {
|
|
203
204
|
className: "flex items-center gap-2",
|
|
204
|
-
children: [/* @__PURE__ */
|
|
205
|
+
children: [/* @__PURE__ */ y(h, {
|
|
205
206
|
size: 16,
|
|
206
207
|
className: "text-text-secondary"
|
|
207
|
-
}), /* @__PURE__ */
|
|
208
|
+
}), /* @__PURE__ */ b("span", { children: ["$", (e.totalRevenue || 0).toLocaleString()] })]
|
|
208
209
|
})
|
|
209
210
|
]
|
|
210
211
|
})]
|
|
211
|
-
}), /* @__PURE__ */
|
|
212
|
+
}), /* @__PURE__ */ b("div", {
|
|
212
213
|
className: "mt-4 grid grid-cols-2 gap-4 rounded-lg bg-bg-sunken/50 p-4 sm:grid-cols-4",
|
|
213
214
|
children: [
|
|
214
|
-
/* @__PURE__ */
|
|
215
|
+
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
215
216
|
className: "text-xs text-text-secondary",
|
|
216
217
|
children: r("devportal.totalInstalls", "Total Installs")
|
|
217
|
-
}), /* @__PURE__ */
|
|
218
|
+
}), /* @__PURE__ */ y("p", {
|
|
218
219
|
className: "text-lg font-semibold",
|
|
219
220
|
children: (e.totalInstalls || 0).toLocaleString()
|
|
220
221
|
})] }),
|
|
221
|
-
/* @__PURE__ */
|
|
222
|
+
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
222
223
|
className: "text-xs text-text-secondary",
|
|
223
224
|
children: r("devportal.activeInstalls", "Active Installs")
|
|
224
|
-
}), /* @__PURE__ */
|
|
225
|
+
}), /* @__PURE__ */ y("p", {
|
|
225
226
|
className: "text-lg font-semibold",
|
|
226
227
|
children: (e.activeInstalls || 0).toLocaleString()
|
|
227
228
|
})] }),
|
|
228
|
-
/* @__PURE__ */
|
|
229
|
+
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
229
230
|
className: "text-xs text-text-secondary",
|
|
230
231
|
children: r("devportal.apiCalls", "API Calls")
|
|
231
|
-
}), /* @__PURE__ */
|
|
232
|
+
}), /* @__PURE__ */ y("p", {
|
|
232
233
|
className: "text-lg font-semibold",
|
|
233
234
|
children: e.totalApiCalls ? `${(parseInt(e.totalApiCalls) / 1e6).toFixed(1)}M` : "0"
|
|
234
235
|
})] }),
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
+
/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
|
|
236
237
|
className: "text-xs text-text-secondary",
|
|
237
238
|
children: r("devportal.avgRating", "Avg Rating")
|
|
238
|
-
}), /* @__PURE__ */
|
|
239
|
+
}), /* @__PURE__ */ y("p", {
|
|
239
240
|
className: "text-lg font-semibold",
|
|
240
241
|
children: e.averageRating ? `${e.averageRating.toFixed(1)} ★` : r("devportal.notAvailable", "N/A")
|
|
241
242
|
})] })
|
|
@@ -244,6 +245,6 @@ var x = () => {
|
|
|
244
245
|
});
|
|
245
246
|
};
|
|
246
247
|
//#endregion
|
|
247
|
-
export {
|
|
248
|
+
export { C as OrganizationsPage };
|
|
248
249
|
|
|
249
250
|
//# sourceMappingURL=OrganizationsPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OrganizationsPage.js","names":[],"sources":["../../../src/devportal/pages/OrganizationsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Plus,\n Building2,\n Users,\n AppWindow,\n DollarSign,\n CheckCircle,\n AlertCircle,\n Loader2,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatusBadge, VerifiedBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { useTr } from \"../utils/i18n\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n useGetMyOrganizationsQuery,\n getErrorMessage,\n type OrganizationFieldsFragment,\n} from \"../hooks\";\n\n/**\n * Organizations listing page\n *\n * Displays all developer organizations the current user is a member of.\n * Uses GraphQL to fetch real data from the DevPortal backend.\n */\nexport const OrganizationsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n\n // Fetch organizations from GraphQL API\n const { data, loading, error, refetch } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n const organizations = data?.myDeveloperOrganizations ?? [];\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n // Loading state\n if (loading && !data) {\n return (\n <PageLayout\n title={tr(\n \"devportal.developerOrganizations\",\n \"Developer Organizations\",\n )}\n description={tr(\n \"devportal.manageYourDevTeams\",\n \"Manage your development teams\",\n )}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-text-secondary\">\n {tr(\"devportal.loadingOrganizations\", \"Loading organizations...\")}\n </span>\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error) {\n return (\n <PageLayout\n title={tr(\n \"devportal.developerOrganizations\",\n \"Developer Organizations\",\n )}\n description={tr(\n \"devportal.manageYourDevTeams\",\n \"Manage your development teams\",\n )}\n >\n <div className=\"rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center\">\n <AlertCircle className=\"mx-auto h-8 w-8 text-status-error-text\" />\n <h3 className=\"mt-2 font-medium text-status-error-text\">\n {tr(\n \"devportal.failedToLoadOrganizations\",\n \"Failed to load organizations\",\n )}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n <button\n onClick={() => refetch()}\n className=\"mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n {tr(\"devportal.tryAgain\", \"Try Again\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\n \"devportal.developerOrganizations\",\n \"Developer Organizations\",\n )}\n description={tr(\n \"devportal.manageYourDevTeams\",\n \"Manage your development teams\",\n )}\n purpose={tr(\n \"devportal.organizationsPurpose\",\n \"An organization is the team that owns your apps, members, and revenue. Create one so collaborators can share access to the same applications, billing, and store presence instead of working in isolation.\",\n )}\n actions={\n <button\n onClick={() => handleNavigate(\"/organizations/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </button>\n }\n >\n {organizations.length > 0 && (\n <EmphasisPanel className=\"mb-6\">\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.organizations\", \"Organizations\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations.length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.totalApps\", \"Total Apps\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.totalApps ?? 0),\n 0,\n )}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.activeInstalls\", \"Active Installs\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations\n .reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.activeInstalls ?? 0),\n 0,\n )\n .toLocaleString()}\n </p>\n </GlassCard>\n </div>\n </EmphasisPanel>\n )}\n {organizations.length > 0 ? (\n <div className=\"grid gap-6\">\n {organizations.map((org: OrganizationFieldsFragment) => (\n <OrganizationCard\n key={org.id}\n org={org as DeveloperOrganization}\n onClick={() => handleNavigate(`/organizations/${org.id}`)}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n title={tr(\"devportal.noOrganizationsYet\", \"No organizations yet\")}\n description={tr(\n \"devportal.createOrgToCollaborate\",\n \"Create an organization to collaborate with your team and manage apps together\",\n )}\n action={\n <button\n onClick={() => handleNavigate(\"/organizations/new\")}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </button>\n }\n />\n )}\n </PageLayout>\n </PermissionGuard>\n );\n};\n\n// Organization card component\nconst OrganizationCard: FC<{\n org: DeveloperOrganization;\n onClick: () => void;\n}> = ({ org, onClick }) => {\n const tr = useTr();\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onClick();\n }\n }}\n className=\"cursor-pointer rounded-card border border-border-seam bg-bg-surface p-6 shadow-[var(--shadow-pop)] transition-[box-shadow,border-color] hover:shadow-[var(--shadow-pop-hover)] hover:border-border-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n >\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n {/* Left side - Info */}\n <div className=\"flex items-start gap-4\">\n {org.logoUrl ? (\n <img\n src={org.logoUrl}\n alt={org.name}\n className=\"h-16 w-16 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Building2 size={32} />\n </div>\n )}\n <div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h3 className=\"text-lg font-semibold\">{org.name}</h3>\n {org.isVerified && <VerifiedBadge verified />}\n {org.isCertified && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-info-bg-subtle px-2 py-0.5 text-xs font-medium text-status-info-text\">\n <CheckCircle size={12} />{\" \"}\n {tr(\"devportal.certified\", \"Certified\")}\n </span>\n )}\n </div>\n {org.description && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {org.description}\n </p>\n )}\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusBadge status={org.tier} type=\"tier\" />\n {org.partnerTier && (\n <StatusBadge status={org.partnerTier} type=\"partner\" />\n )}\n </div>\n </div>\n </div>\n\n {/* Right side - Stats */}\n <div className=\"flex flex-wrap gap-6 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Users size={16} className=\"text-text-secondary\" />\n <span>\n {org.members?.length || 0}{\" \"}\n {tr(\"devportal.membersLower\", \"members\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AppWindow size={16} className=\"text-text-secondary\" />\n <span>\n {org.publishedApps} / {org.totalApps}{\" \"}\n {tr(\"devportal.appsLower\", \"apps\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <DollarSign size={16} className=\"text-text-secondary\" />\n <span>${(org.totalRevenue || 0).toLocaleString()}</span>\n </div>\n </div>\n </div>\n\n {/* Stats bar */}\n <div className=\"mt-4 grid grid-cols-2 gap-4 rounded-lg bg-bg-sunken/50 p-4 sm:grid-cols-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.totalInstalls\", \"Total Installs\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {(org.totalInstalls || 0).toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.activeInstalls\", \"Active Installs\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {(org.activeInstalls || 0).toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.apiCalls\", \"API Calls\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {org.totalApiCalls\n ? `${(parseInt(org.totalApiCalls) / 1000000).toFixed(1)}M`\n : \"0\"}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.avgRating\", \"Avg Rating\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {org.averageRating\n ? `${org.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")}\n </p>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OrganizationsPage.js","names":[],"sources":["../../../src/devportal/pages/OrganizationsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport {\n Plus,\n Building2,\n Users,\n AppWindow,\n DollarSign,\n CheckCircle,\n AlertCircle,\n Loader2,\n} from \"lucide-react\";\nimport { EmphasisPanel, GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { StatusBadge, VerifiedBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { useTr } from \"../utils/i18n\";\nimport {\n useIsSellerSection,\n orgSectionPath,\n} from \"../hooks/useIsSellerSection\";\nimport type { DeveloperOrganization } from \"../types\";\nimport {\n useGetMyOrganizationsQuery,\n getErrorMessage,\n type OrganizationFieldsFragment,\n} from \"../hooks\";\n\n/**\n * Organizations listing page\n *\n * Displays all developer organizations the current user is a member of.\n * Uses GraphQL to fetch real data from the DevPortal backend.\n */\nexport const OrganizationsPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const tr = useTr();\n const isSeller = useIsSellerSection();\n\n // Fetch organizations from GraphQL API\n const { data, loading, error, refetch } = useGetMyOrganizationsQuery({\n fetchPolicy: \"cache-and-network\",\n });\n\n // Shared page for both DIGITAL orgs (regular devportal) and PHYSICAL orgs\n // (seller portal) — filtered by which section it's reached from. See\n // DeveloperOrgKind (BOFF-7285).\n const organizations = (data?.myDeveloperOrganizations ?? []).filter(\n (org: OrganizationFieldsFragment) =>\n isSeller ? org.kind === \"PHYSICAL\" : org.kind !== \"PHYSICAL\",\n );\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const createPath = orgSectionPath(isSeller, \"new\");\n const detailPath = (orgId: string) => orgSectionPath(isSeller, orgId);\n\n const pageTitle = isSeller\n ? tr(\"devportal.sellerOrganizations\", \"Seller Organizations\")\n : tr(\"devportal.developerOrganizations\", \"Developer Organizations\");\n const pageDescription = isSeller\n ? tr(\n \"devportal.manageYourSellerOrgs\",\n \"Manage the organizations you sell physical goods under\",\n )\n : tr(\"devportal.manageYourDevTeams\", \"Manage your development teams\");\n\n // Loading state\n if (loading && !data) {\n return (\n <PageLayout title={pageTitle} description={pageDescription}>\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-text-secondary\">\n {tr(\"devportal.loadingOrganizations\", \"Loading organizations...\")}\n </span>\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (error) {\n return (\n <PageLayout title={pageTitle} description={pageDescription}>\n <div className=\"rounded-lg border border-status-error-border/50 bg-status-error-bg/10 p-6 text-center\">\n <AlertCircle className=\"mx-auto h-8 w-8 text-status-error-text\" />\n <h3 className=\"mt-2 font-medium text-status-error-text\">\n {tr(\n \"devportal.failedToLoadOrganizations\",\n \"Failed to load organizations\",\n )}\n </h3>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {getErrorMessage(error)}\n </p>\n <button\n onClick={() => refetch()}\n className=\"mt-4 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n {tr(\"devportal.tryAgain\", \"Try Again\")}\n </button>\n </div>\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={pageTitle}\n description={pageDescription}\n purpose={\n isSeller\n ? tr(\n \"devportal.sellerOrganizationsPurpose\",\n \"A seller organization owns your physical listings, orders, and revenue. It's created automatically the first time you list an item, or you can create one here.\",\n )\n : tr(\n \"devportal.organizationsPurpose\",\n \"An organization is the team that owns your apps, members, and revenue. Create one so collaborators can share access to the same applications, billing, and store presence instead of working in isolation.\",\n )\n }\n actions={\n <button\n onClick={() => handleNavigate(createPath)}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors\"\n >\n <Plus size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </button>\n }\n >\n {organizations.length > 0 && (\n <EmphasisPanel className=\"mb-6\">\n <div className=\"grid grid-cols-2 gap-4 sm:grid-cols-3\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.organizations\", \"Organizations\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations.length}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.totalApps\", \"Total Apps\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations.reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.totalApps ?? 0),\n 0,\n )}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <p className=\"text-sm text-text-secondary\">\n {tr(\"devportal.activeInstalls\", \"Active Installs\")}\n </p>\n <p className=\"mt-1 text-2xl font-semibold tabular-nums\">\n {organizations\n .reduce(\n (acc: number, org: OrganizationFieldsFragment) =>\n acc + (org.activeInstalls ?? 0),\n 0,\n )\n .toLocaleString()}\n </p>\n </GlassCard>\n </div>\n </EmphasisPanel>\n )}\n {organizations.length > 0 ? (\n <div className=\"grid gap-6\">\n {organizations.map((org: OrganizationFieldsFragment) => (\n <OrganizationCard\n key={org.id}\n org={org as DeveloperOrganization}\n onClick={() => handleNavigate(detailPath(org.id))}\n />\n ))}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-people\"\n title={\n isSeller\n ? tr(\n \"devportal.noSellerOrganizationsYet\",\n \"No seller organizations yet\",\n )\n : tr(\"devportal.noOrganizationsYet\", \"No organizations yet\")\n }\n description={\n isSeller\n ? tr(\n \"devportal.createSellerOrgToSell\",\n \"Create a seller organization to start selling physical products, or list your first item and one will be set up for you\",\n )\n : tr(\n \"devportal.createOrgToCollaborate\",\n \"Create an organization to collaborate with your team and manage apps together\",\n )\n }\n action={\n <button\n onClick={() => handleNavigate(createPath)}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90\"\n >\n <Plus size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </button>\n }\n />\n )}\n </PageLayout>\n </PermissionGuard>\n );\n};\n\n// Organization card component\nconst OrganizationCard: FC<{\n org: DeveloperOrganization;\n onClick: () => void;\n}> = ({ org, onClick }) => {\n const tr = useTr();\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={onClick}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n onClick();\n }\n }}\n className=\"cursor-pointer rounded-card border border-border-seam bg-bg-surface p-6 shadow-[var(--shadow-pop)] transition-[box-shadow,border-color] hover:shadow-[var(--shadow-pop-hover)] hover:border-border-strong focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n >\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n {/* Left side - Info */}\n <div className=\"flex items-start gap-4\">\n {org.logoUrl ? (\n <img\n src={org.logoUrl}\n alt={org.name}\n className=\"h-16 w-16 rounded-lg object-cover\"\n />\n ) : (\n <div className=\"flex h-16 w-16 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Building2 size={32} />\n </div>\n )}\n <div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h3 className=\"text-lg font-semibold\">{org.name}</h3>\n {org.isVerified && <VerifiedBadge verified />}\n {org.isCertified && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-status-info-bg-subtle px-2 py-0.5 text-xs font-medium text-status-info-text\">\n <CheckCircle size={12} />{\" \"}\n {tr(\"devportal.certified\", \"Certified\")}\n </span>\n )}\n </div>\n {org.description && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {org.description}\n </p>\n )}\n <div className=\"mt-2 flex flex-wrap items-center gap-2\">\n <StatusBadge status={org.tier} type=\"tier\" />\n {org.partnerTier && (\n <StatusBadge status={org.partnerTier} type=\"partner\" />\n )}\n </div>\n </div>\n </div>\n\n {/* Right side - Stats */}\n <div className=\"flex flex-wrap gap-6 text-sm\">\n <div className=\"flex items-center gap-2\">\n <Users size={16} className=\"text-text-secondary\" />\n <span>\n {org.members?.length || 0}{\" \"}\n {tr(\"devportal.membersLower\", \"members\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AppWindow size={16} className=\"text-text-secondary\" />\n <span>\n {org.publishedApps} / {org.totalApps}{\" \"}\n {tr(\"devportal.appsLower\", \"apps\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <DollarSign size={16} className=\"text-text-secondary\" />\n <span>${(org.totalRevenue || 0).toLocaleString()}</span>\n </div>\n </div>\n </div>\n\n {/* Stats bar */}\n <div className=\"mt-4 grid grid-cols-2 gap-4 rounded-lg bg-bg-sunken/50 p-4 sm:grid-cols-4\">\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.totalInstalls\", \"Total Installs\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {(org.totalInstalls || 0).toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.activeInstalls\", \"Active Installs\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {(org.activeInstalls || 0).toLocaleString()}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.apiCalls\", \"API Calls\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {org.totalApiCalls\n ? `${(parseInt(org.totalApiCalls) / 1000000).toFixed(1)}M`\n : \"0\"}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.avgRating\", \"Avg Rating\")}\n </p>\n <p className=\"text-lg font-semibold\">\n {org.averageRating\n ? `${org.averageRating.toFixed(1)} ★`\n : tr(\"devportal.notAvailable\", \"N/A\")}\n </p>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RevenueDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"RevenueDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/RevenueDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAiEhC,eAAO,MAAM,oBAAoB,EAAE,EA6xBlC,CAAC"}
|