@burdenoff/microfe-devportal 2026.1112.1 → 2026.1112.2
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/pages/CreateOrganizationPage.js +120 -114
- package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.js +84 -73
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientDetailPage.js +134 -115
- package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
- package/dist/devportal/pages/SetupPage.js +141 -143
- package/dist/devportal/pages/SetupPage.js.map +1 -1
- package/dist/devportal/utils/errorMessage.d.ts +2 -0
- package/dist/devportal/utils/errorMessage.js +7 -0
- package/dist/devportal/utils/errorMessage.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
import { PageLayout as e, PageSection as t } from "../components/PageLayout.js";
|
|
2
2
|
import { InputField as n, TextareaField as r } from "../components/FormField.js";
|
|
3
|
-
import { useDevportal as
|
|
3
|
+
import { useDevportal as ee } from "../providers/DevportalProvider.js";
|
|
4
4
|
import "../components/index.js";
|
|
5
|
-
import { orgSectionPath as
|
|
6
|
-
import { useCreateBillingAccountMutation as
|
|
5
|
+
import { orgSectionPath as i, useIsSellerSection as a } from "../hooks/useIsSellerSection.js";
|
|
6
|
+
import { useCreateBillingAccountMutation as o, useCreateOrganizationMutation as s, useCreateSellerOrganizationMutation as c, useGetBillingAccountsByOrgQuery as l, useLinkDevOrgBillingAccountMutation as u } from "../../generated/global-operations.js";
|
|
7
7
|
import "../hooks/index.js";
|
|
8
|
-
import { useDevportalEventBus as
|
|
9
|
-
import { PermissionGuard as
|
|
10
|
-
import { cn as
|
|
11
|
-
import { useTr as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
8
|
+
import { useDevportalEventBus as d } from "../events/index.js";
|
|
9
|
+
import { PermissionGuard as f } from "../components/PermissionGuard.js";
|
|
10
|
+
import { cn as p } from "../utils/cn.js";
|
|
11
|
+
import { useTr as m } from "../utils/i18n.js";
|
|
12
|
+
import { errorMessage as h } from "../utils/errorMessage.js";
|
|
13
|
+
import { useEffect as te, useMemo as ne, useState as g } from "react";
|
|
14
|
+
import { Building2 as _, Check as v, Link2 as y, Loader2 as b, X as x } from "lucide-react";
|
|
15
|
+
import { Fragment as S, jsx as C, jsxs as w } from "react/jsx-runtime";
|
|
15
16
|
// src/devportal/pages/CreateOrganizationPage.tsx
|
|
16
|
-
var
|
|
17
|
-
let { navigate:
|
|
17
|
+
var T = () => {
|
|
18
|
+
let { navigate: T, basePath: E, currentUser: D, tenantId: O, setActiveOrgId: re, setActivePhysicalOrgId: ie } = ee(), k = a(), A = m(), [j, M] = g({}), [N, P] = g(null), [F] = s(), [I] = c(), [L] = o(), [R] = u(), z = d(), [B, V] = g("idle"), H = B !== "idle", [U, W] = g("auto"), [G, K] = g(null), { data: q, loading: J } = l({
|
|
18
19
|
fetchPolicy: "cache-and-network",
|
|
19
|
-
context: { headers: { "x-org-id":
|
|
20
|
-
}), Y =
|
|
21
|
-
|
|
20
|
+
context: { headers: { "x-org-id": O ?? "" } }
|
|
21
|
+
}), Y = ne(() => q?.getBillingAccountsByOrg ?? [], [q]);
|
|
22
|
+
te(() => {
|
|
22
23
|
U !== "existing" || J || (Y.length === 0 ? W("auto") : G || K(Y.find((e) => e.isDefault)?.id ?? Y[0]?.id ?? null));
|
|
23
24
|
}, [
|
|
24
25
|
U,
|
|
@@ -26,7 +27,7 @@ var E = () => {
|
|
|
26
27
|
Y,
|
|
27
28
|
G
|
|
28
29
|
]);
|
|
29
|
-
let [X, Z] =
|
|
30
|
+
let [X, Z] = g({
|
|
30
31
|
name: "",
|
|
31
32
|
slug: "",
|
|
32
33
|
description: "",
|
|
@@ -34,14 +35,14 @@ var E = () => {
|
|
|
34
35
|
contactEmail: "",
|
|
35
36
|
supportEmail: ""
|
|
36
37
|
}), Q = (e) => {
|
|
37
|
-
|
|
38
|
-
},
|
|
38
|
+
T?.(`${E}${e}`);
|
|
39
|
+
}, ae = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), oe = (e) => {
|
|
39
40
|
let t = e.target.value;
|
|
40
41
|
Z((e) => ({
|
|
41
42
|
...e,
|
|
42
43
|
name: t,
|
|
43
|
-
slug: e.slug ||
|
|
44
|
-
})),
|
|
44
|
+
slug: e.slug || ae(t)
|
|
45
|
+
})), j.name && M((e) => ({
|
|
45
46
|
...e,
|
|
46
47
|
name: void 0
|
|
47
48
|
}));
|
|
@@ -49,26 +50,26 @@ var E = () => {
|
|
|
49
50
|
Z((n) => ({
|
|
50
51
|
...n,
|
|
51
52
|
[e]: t
|
|
52
|
-
})),
|
|
53
|
+
})), j[e] && M((t) => ({
|
|
53
54
|
...t,
|
|
54
55
|
[e]: void 0
|
|
55
56
|
}));
|
|
56
|
-
},
|
|
57
|
+
}, se = () => {
|
|
57
58
|
let e = {};
|
|
58
|
-
return X.name.trim() ? X.name.length < 2 ? e.name =
|
|
59
|
+
return X.name.trim() ? X.name.length < 2 ? e.name = A("devportal.orgNameTooShort", "Name must be at least 2 characters") : X.name.length > 100 && (e.name = A("devportal.nameTooLong", "Name must be less than 100 characters")) : e.name = A("devportal.orgNameRequired", "Organization name is required"), X.slug.trim() ? /^[a-z0-9-]+$/.test(X.slug) || (e.slug = A("devportal.slugInvalid", "Slug can only contain lowercase letters, numbers, and hyphens")) : e.slug = A("devportal.slugRequired", "Slug is required"), X.contactEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(X.contactEmail) && (e.contactEmail = A("devportal.invalidEmailAddress", "Invalid email address")), X.supportEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(X.supportEmail) && (e.supportEmail = A("devportal.invalidEmailAddress", "Invalid email address")), M(e), Object.keys(e).length === 0;
|
|
59
60
|
};
|
|
60
|
-
return /* @__PURE__ */
|
|
61
|
+
return /* @__PURE__ */ C(f, {
|
|
61
62
|
authOnly: !0,
|
|
62
|
-
children: /* @__PURE__ */
|
|
63
|
-
title:
|
|
64
|
-
description:
|
|
65
|
-
purpose:
|
|
66
|
-
backLink: `${
|
|
67
|
-
backLabel:
|
|
68
|
-
children: /* @__PURE__ */
|
|
63
|
+
children: /* @__PURE__ */ C(e, {
|
|
64
|
+
title: A("devportal.createOrganization", "Create Organization"),
|
|
65
|
+
description: k ? A("devportal.createSellerOrganizationDescription", "Set up a seller organization to start selling physical products") : A("devportal.createOrganizationDescription", "Set up a developer organization to collaborate with your team"),
|
|
66
|
+
purpose: k ? A("devportal.createSellerOrganizationPurpose", "A seller organization is the shared owner of your physical listings, orders, and revenue. Create one here — you can invite members and complete legal/tax details afterwards.") : A("devportal.createOrganizationPurpose", "An organization is the shared owner of your apps, members, and revenue. Create one here so your team works under a single identity — pick a name and tier now; you can invite members and verify it afterwards."),
|
|
67
|
+
backLink: `${E}${i(k)}`,
|
|
68
|
+
backLabel: A("devportal.backToOrganizations", "Back to Organizations"),
|
|
69
|
+
children: /* @__PURE__ */ w("form", {
|
|
69
70
|
onSubmit: async (e) => {
|
|
70
|
-
if (e.preventDefault(),
|
|
71
|
-
V("creating-org");
|
|
71
|
+
if (e.preventDefault(), se()) {
|
|
72
|
+
P(null), V("creating-org");
|
|
72
73
|
try {
|
|
73
74
|
let e = {
|
|
74
75
|
name: X.name,
|
|
@@ -77,7 +78,7 @@ var E = () => {
|
|
|
77
78
|
websiteUrl: X.websiteUrl || void 0,
|
|
78
79
|
contactEmail: X.contactEmail || void 0,
|
|
79
80
|
supportEmail: X.supportEmail || void 0
|
|
80
|
-
}, t =
|
|
81
|
+
}, t = k ? (await I({ variables: { input: e } })).data?.createSellerOrganization?.id : (await F({ variables: { input: e } })).data?.createDeveloperOrganization?.id;
|
|
81
82
|
if (!t) {
|
|
82
83
|
V("idle");
|
|
83
84
|
return;
|
|
@@ -85,7 +86,7 @@ var E = () => {
|
|
|
85
86
|
if (z.emit("devportal.org.created", {
|
|
86
87
|
organizationId: t,
|
|
87
88
|
name: X.name
|
|
88
|
-
}),
|
|
89
|
+
}), k ? ie(t) : re(t), U === "existing" && G) {
|
|
89
90
|
V("linking-billing");
|
|
90
91
|
try {
|
|
91
92
|
await R({ variables: {
|
|
@@ -98,7 +99,7 @@ var E = () => {
|
|
|
98
99
|
try {
|
|
99
100
|
let e = (await L({ variables: { input: {
|
|
100
101
|
name: X.name,
|
|
101
|
-
email:
|
|
102
|
+
email: D?.email ?? ""
|
|
102
103
|
} } })).data?.createBillingAccount?.id;
|
|
103
104
|
e && await R({ variables: {
|
|
104
105
|
organizationId: t,
|
|
@@ -106,135 +107,140 @@ var E = () => {
|
|
|
106
107
|
} });
|
|
107
108
|
} catch {}
|
|
108
109
|
}
|
|
109
|
-
V("redirecting"), Q(
|
|
110
|
+
V("redirecting"), Q(i(k, t));
|
|
110
111
|
} catch (e) {
|
|
111
|
-
console.error("Failed to create organization:", e), V("idle");
|
|
112
|
+
console.error("Failed to create organization:", e), P(h(e, A("devportal.createOrganizationFailed", "We could not create your organization. Your details are still here, so you can try again."))), V("idle");
|
|
112
113
|
}
|
|
113
114
|
}
|
|
114
115
|
},
|
|
115
116
|
className: "space-y-8 max-w-3xl",
|
|
116
117
|
children: [
|
|
117
|
-
/* @__PURE__ */
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
children:
|
|
118
|
+
N && /* @__PURE__ */ C("div", {
|
|
119
|
+
role: "alert",
|
|
120
|
+
className: "rounded-md bg-status-error-bg px-3 py-2 text-sm text-status-error-text",
|
|
121
|
+
children: N
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ C(t, {
|
|
124
|
+
title: A("devportal.organizationDetails", "Organization Details"),
|
|
125
|
+
description: A("devportal.organizationDetailsDescription", "Basic information about your organization"),
|
|
126
|
+
children: /* @__PURE__ */ w("div", {
|
|
121
127
|
className: "space-y-4",
|
|
122
128
|
children: [
|
|
123
|
-
/* @__PURE__ */
|
|
124
|
-
label:
|
|
129
|
+
/* @__PURE__ */ C(n, {
|
|
130
|
+
label: A("devportal.organizationName", "Organization Name"),
|
|
125
131
|
value: X.name,
|
|
126
|
-
onChange:
|
|
127
|
-
placeholder:
|
|
132
|
+
onChange: oe,
|
|
133
|
+
placeholder: A("devportal.organizationNamePlaceholder", "Acme Development"),
|
|
128
134
|
required: !0,
|
|
129
|
-
error:
|
|
130
|
-
hint:
|
|
135
|
+
error: j.name,
|
|
136
|
+
hint: A("devportal.organizationNameHint", "Your organization's display name")
|
|
131
137
|
}),
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
-
label:
|
|
138
|
+
/* @__PURE__ */ C(n, {
|
|
139
|
+
label: A("devportal.slug", "Slug"),
|
|
134
140
|
value: X.slug,
|
|
135
141
|
onChange: (e) => $("slug", e.target.value.toLowerCase()),
|
|
136
|
-
placeholder:
|
|
142
|
+
placeholder: A("devportal.orgSlugPlaceholder", "acme-dev"),
|
|
137
143
|
required: !0,
|
|
138
|
-
error:
|
|
139
|
-
hint:
|
|
144
|
+
error: j.slug,
|
|
145
|
+
hint: A("devportal.slugHint", "URL-friendly identifier (auto-generated from name)")
|
|
140
146
|
}),
|
|
141
|
-
/* @__PURE__ */
|
|
142
|
-
label:
|
|
147
|
+
/* @__PURE__ */ C(r, {
|
|
148
|
+
label: A("devportal.description", "Description"),
|
|
143
149
|
value: X.description,
|
|
144
150
|
onChange: (e) => $("description", e.target.value),
|
|
145
|
-
placeholder:
|
|
151
|
+
placeholder: A("devportal.orgDescriptionPlaceholder", "Tell us about your organization..."),
|
|
146
152
|
rows: 3
|
|
147
153
|
}),
|
|
148
|
-
/* @__PURE__ */
|
|
149
|
-
label:
|
|
154
|
+
/* @__PURE__ */ C(n, {
|
|
155
|
+
label: A("devportal.websiteUrl", "Website URL"),
|
|
150
156
|
type: "url",
|
|
151
157
|
value: X.websiteUrl,
|
|
152
158
|
onChange: (e) => $("websiteUrl", e.target.value),
|
|
153
159
|
placeholder: "https://example.com"
|
|
154
160
|
}),
|
|
155
|
-
/* @__PURE__ */
|
|
161
|
+
/* @__PURE__ */ w("div", {
|
|
156
162
|
className: "grid gap-4 sm:grid-cols-2",
|
|
157
|
-
children: [/* @__PURE__ */
|
|
158
|
-
label:
|
|
163
|
+
children: [/* @__PURE__ */ C(n, {
|
|
164
|
+
label: A("devportal.contactEmail", "Contact Email"),
|
|
159
165
|
type: "email",
|
|
160
166
|
value: X.contactEmail,
|
|
161
167
|
onChange: (e) => $("contactEmail", e.target.value),
|
|
162
168
|
placeholder: "contact@example.com",
|
|
163
|
-
error:
|
|
164
|
-
}), /* @__PURE__ */
|
|
165
|
-
label:
|
|
169
|
+
error: j.contactEmail
|
|
170
|
+
}), /* @__PURE__ */ C(n, {
|
|
171
|
+
label: A("devportal.supportEmail", "Support Email"),
|
|
166
172
|
type: "email",
|
|
167
173
|
value: X.supportEmail,
|
|
168
174
|
onChange: (e) => $("supportEmail", e.target.value),
|
|
169
175
|
placeholder: "support@example.com",
|
|
170
|
-
error:
|
|
176
|
+
error: j.supportEmail
|
|
171
177
|
})]
|
|
172
178
|
})
|
|
173
179
|
]
|
|
174
180
|
})
|
|
175
181
|
}),
|
|
176
|
-
/* @__PURE__ */
|
|
177
|
-
title:
|
|
178
|
-
description:
|
|
179
|
-
children: /* @__PURE__ */
|
|
182
|
+
/* @__PURE__ */ C(t, {
|
|
183
|
+
title: A("devportal.billingAccount", "Billing Account"),
|
|
184
|
+
description: A("devportal.billingAccountSectionDescription", "Revenue from sales will be credited here. You can change this anytime from the Revenue page."),
|
|
185
|
+
children: /* @__PURE__ */ w("div", {
|
|
180
186
|
className: "space-y-3",
|
|
181
187
|
children: [
|
|
182
|
-
/* @__PURE__ */
|
|
188
|
+
/* @__PURE__ */ w("button", {
|
|
183
189
|
type: "button",
|
|
184
190
|
onClick: () => W("auto"),
|
|
185
191
|
disabled: H,
|
|
186
|
-
className:
|
|
187
|
-
children: [/* @__PURE__ */
|
|
192
|
+
className: p("flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50", U === "auto" ? "border-primary bg-action-primary-bg/5" : "border-border-subtle hover:bg-bg-sunken"),
|
|
193
|
+
children: [/* @__PURE__ */ C(v, {
|
|
188
194
|
size: 16,
|
|
189
|
-
className:
|
|
190
|
-
}), /* @__PURE__ */
|
|
195
|
+
className: p("mt-0.5 flex-shrink-0", U === "auto" ? "opacity-100 text-primary" : "opacity-0")
|
|
196
|
+
}), /* @__PURE__ */ w("div", {
|
|
191
197
|
className: "flex-1 min-w-0",
|
|
192
|
-
children: [/* @__PURE__ */
|
|
198
|
+
children: [/* @__PURE__ */ C("p", {
|
|
193
199
|
className: "text-sm font-medium",
|
|
194
|
-
children:
|
|
195
|
-
}), /* @__PURE__ */
|
|
200
|
+
children: A("devportal.billingAutoCreate", "Create a new billing account automatically")
|
|
201
|
+
}), /* @__PURE__ */ C("p", {
|
|
196
202
|
className: "mt-0.5 text-xs text-text-secondary",
|
|
197
|
-
children:
|
|
203
|
+
children: A("devportal.billingAutoCreateHint", "We'll set one up using your organization name and account email. You can complete legal and tax details for payouts later in Organization Settings.")
|
|
198
204
|
})]
|
|
199
205
|
})]
|
|
200
206
|
}),
|
|
201
|
-
/* @__PURE__ */
|
|
207
|
+
/* @__PURE__ */ w("button", {
|
|
202
208
|
type: "button",
|
|
203
209
|
onClick: () => W("existing"),
|
|
204
210
|
disabled: H || !J && Y.length === 0,
|
|
205
|
-
className:
|
|
206
|
-
children: [/* @__PURE__ */
|
|
211
|
+
className: p("flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50", U === "existing" ? "border-primary bg-action-primary-bg/5" : "border-border-subtle hover:bg-bg-sunken"),
|
|
212
|
+
children: [/* @__PURE__ */ C(v, {
|
|
207
213
|
size: 16,
|
|
208
|
-
className:
|
|
209
|
-
}), /* @__PURE__ */
|
|
214
|
+
className: p("mt-0.5 flex-shrink-0", U === "existing" ? "opacity-100 text-primary" : "opacity-0")
|
|
215
|
+
}), /* @__PURE__ */ w("div", {
|
|
210
216
|
className: "flex-1 min-w-0",
|
|
211
|
-
children: [/* @__PURE__ */
|
|
217
|
+
children: [/* @__PURE__ */ w("p", {
|
|
212
218
|
className: "flex items-center gap-1.5 text-sm font-medium",
|
|
213
|
-
children: [/* @__PURE__ */
|
|
214
|
-
}), /* @__PURE__ */
|
|
219
|
+
children: [/* @__PURE__ */ C(y, { size: 14 }), A("devportal.billingLinkExisting", "Link an existing billing account")]
|
|
220
|
+
}), /* @__PURE__ */ C("p", {
|
|
215
221
|
className: "mt-0.5 text-xs text-text-secondary",
|
|
216
|
-
children: J ?
|
|
222
|
+
children: J ? A("devportal.billingAccountsLoading", "Loading your billing accounts...") : Y.length === 0 ? A("devportal.noBillingAccountsYet", "You don't have any billing accounts yet — create one from account billing settings first.") : A("devportal.billingAccountsAvailable", "{{count}} billing account(s) available to link", { count: Y.length })
|
|
217
223
|
})]
|
|
218
224
|
})]
|
|
219
225
|
}),
|
|
220
|
-
U === "existing" && Y.length > 0 && /* @__PURE__ */
|
|
226
|
+
U === "existing" && Y.length > 0 && /* @__PURE__ */ C("div", {
|
|
221
227
|
className: "ml-8 space-y-2",
|
|
222
|
-
children: Y.map((e) => /* @__PURE__ */
|
|
228
|
+
children: Y.map((e) => /* @__PURE__ */ w("button", {
|
|
223
229
|
type: "button",
|
|
224
230
|
disabled: H,
|
|
225
231
|
onClick: () => K(e.id ?? null),
|
|
226
|
-
className:
|
|
227
|
-
children: [/* @__PURE__ */
|
|
232
|
+
className: p("flex w-full items-center gap-3 rounded-md border px-3 py-2 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", G === e.id ? "border-primary bg-action-primary-bg/5" : "border-border-subtle hover:bg-bg-sunken"),
|
|
233
|
+
children: [/* @__PURE__ */ C(v, {
|
|
228
234
|
size: 14,
|
|
229
|
-
className:
|
|
230
|
-
}), /* @__PURE__ */
|
|
235
|
+
className: p("flex-shrink-0", G === e.id ? "opacity-100 text-primary" : "opacity-0")
|
|
236
|
+
}), /* @__PURE__ */ w("div", {
|
|
231
237
|
className: "min-w-0 flex-1",
|
|
232
|
-
children: [/* @__PURE__ */
|
|
238
|
+
children: [/* @__PURE__ */ C("p", {
|
|
233
239
|
className: "truncate font-medium",
|
|
234
240
|
children: e.name
|
|
235
|
-
}), e.isDefault && /* @__PURE__ */
|
|
241
|
+
}), e.isDefault && /* @__PURE__ */ C("p", {
|
|
236
242
|
className: "text-xs text-text-secondary",
|
|
237
|
-
children:
|
|
243
|
+
children: A("devportal.revenue.defaultAccount", "Default")
|
|
238
244
|
})]
|
|
239
245
|
})]
|
|
240
246
|
}, e.id))
|
|
@@ -242,39 +248,39 @@ var E = () => {
|
|
|
242
248
|
]
|
|
243
249
|
})
|
|
244
250
|
}),
|
|
245
|
-
H && /* @__PURE__ */
|
|
251
|
+
H && /* @__PURE__ */ w("div", {
|
|
246
252
|
className: "flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3 text-sm text-text-secondary",
|
|
247
253
|
children: [
|
|
248
|
-
/* @__PURE__ */
|
|
254
|
+
/* @__PURE__ */ C(b, {
|
|
249
255
|
size: 16,
|
|
250
256
|
className: "flex-shrink-0 animate-spin text-primary"
|
|
251
257
|
}),
|
|
252
|
-
B === "creating-org" &&
|
|
253
|
-
B === "setting-up-billing" &&
|
|
254
|
-
B === "linking-billing" &&
|
|
255
|
-
B === "redirecting" &&
|
|
258
|
+
B === "creating-org" && A("devportal.creatingOrgStatus", "Creating your organization..."),
|
|
259
|
+
B === "setting-up-billing" && A("devportal.settingUpBillingStatus", "Setting up your billing account..."),
|
|
260
|
+
B === "linking-billing" && A("devportal.linkingBillingStatus", "Linking your billing account..."),
|
|
261
|
+
B === "redirecting" && A("devportal.redirectingStatus", "All set — redirecting...")
|
|
256
262
|
]
|
|
257
263
|
}),
|
|
258
|
-
/* @__PURE__ */
|
|
264
|
+
/* @__PURE__ */ w("div", {
|
|
259
265
|
className: "flex items-center justify-end gap-3 border-t pt-6",
|
|
260
|
-
children: [/* @__PURE__ */
|
|
266
|
+
children: [/* @__PURE__ */ w("button", {
|
|
261
267
|
type: "button",
|
|
262
268
|
onClick: () => {
|
|
263
|
-
Q(
|
|
269
|
+
Q(i(k));
|
|
264
270
|
},
|
|
265
271
|
disabled: H,
|
|
266
272
|
className: "inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50",
|
|
267
|
-
children: [/* @__PURE__ */
|
|
268
|
-
}), /* @__PURE__ */
|
|
273
|
+
children: [/* @__PURE__ */ C(x, { size: 16 }), A("devportal.cancel", "Cancel")]
|
|
274
|
+
}), /* @__PURE__ */ C("button", {
|
|
269
275
|
type: "submit",
|
|
270
276
|
disabled: H,
|
|
271
277
|
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 disabled:opacity-50",
|
|
272
|
-
children: H ? /* @__PURE__ */
|
|
273
|
-
/* @__PURE__ */
|
|
274
|
-
B === "setting-up-billing" &&
|
|
275
|
-
B === "linking-billing" &&
|
|
276
|
-
(B === "creating-org" || B === "redirecting") &&
|
|
277
|
-
] }) : /* @__PURE__ */
|
|
278
|
+
children: H ? /* @__PURE__ */ w(S, { children: [
|
|
279
|
+
/* @__PURE__ */ C("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }),
|
|
280
|
+
B === "setting-up-billing" && A("devportal.settingUpBilling", "Setting up billing..."),
|
|
281
|
+
B === "linking-billing" && A("devportal.linkingBilling", "Linking billing..."),
|
|
282
|
+
(B === "creating-org" || B === "redirecting") && A("devportal.creating", "Creating...")
|
|
283
|
+
] }) : /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C(_, { size: 16 }), A("devportal.createOrganization", "Create Organization")] })
|
|
278
284
|
})]
|
|
279
285
|
})
|
|
280
286
|
]
|
|
@@ -282,6 +288,6 @@ var E = () => {
|
|
|
282
288
|
})
|
|
283
289
|
});
|
|
284
290
|
};
|
|
285
|
-
export {
|
|
291
|
+
export { T as CreateOrganizationPage };
|
|
286
292
|
|
|
287
293
|
//# sourceMappingURL=CreateOrganizationPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateOrganizationPage.js","names":["_Fragment","CreateOrganizationPage","useDevportal","isSeller","useIsSellerSection","tr","useTr","errors","setErrors","useState","createOrganization","useCreateOrganizationMutation","createSellerOrganization","useCreateSellerOrganizationMutation","createBillingAccountMutation","useCreateBillingAccountMutation","linkBillingAccount","useLinkDevOrgBillingAccountMutation","bus","useDevportalEventBus","phase","setPhase","isSubmitting","billingChoice","setBillingChoice","selectedBillingAccountId","setSelectedBillingAccountId","billingAccountsData","billingAccountsLoading","useGetBillingAccountsByOrgQuery","tenantId","existingBillingAccounts","useMemo","a","formData","setFormData","handleNavigate","basePath","path","generateSlug","name","handleNameChange","prev","handleChange","field","value","validate","newErrors","PermissionGuard","PageLayout","orgSectionPath","input","orgId","setActivePhysicalOrgId","setActiveOrgId","billingAccountId","currentUser","error","PageSection","InputField","TextareaField","cn","Check","Link2","account","Loader2","X","Fragment","Building2"],"sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { X, Building2, Check, Link2, Loader2 } from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { InputField, TextareaField } from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport {\n useIsSellerSection,\n orgSectionPath,\n} from \"../hooks/useIsSellerSection\";\nimport {\n useCreateOrganizationMutation,\n useCreateSellerOrganizationMutation,\n useGetBillingAccountsByOrgQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../../generated/global-operations\";\nimport { useCreateBillingAccountMutation } from \"../hooks\";\nimport { useDevportalEventBus } from \"../events\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ninterface CreateOrganizationFormData {\n name: string;\n slug: string;\n description: string;\n websiteUrl: string;\n contactEmail: string;\n supportEmail: string;\n}\n\ninterface FormErrors {\n name?: string;\n slug?: string;\n contactEmail?: string;\n supportEmail?: string;\n}\n\ntype SubmitPhase =\n | \"idle\"\n | \"creating-org\"\n | \"setting-up-billing\"\n | \"linking-billing\"\n | \"redirecting\";\n\n/**\n * Create new organization page — single step.\n * The user can either have a billing account auto-created and linked, or\n * link one of their existing billing accounts up front. Legal/tax details\n * are completed later from organization settings.\n */\nexport const CreateOrganizationPage: FC = () => {\n const {\n navigate,\n basePath,\n currentUser,\n tenantId,\n setActiveOrgId,\n setActivePhysicalOrgId,\n } = useDevportal();\n const isSeller = useIsSellerSection();\n const tr = useTr();\n const [errors, setErrors] = useState<FormErrors>({});\n // Shared page for both kinds — which mutation runs is the trust boundary\n // for DeveloperOrgKind (BOFF-7285): createSellerOrganization always makes\n // a PHYSICAL org, createDeveloperOrganization always makes DIGITAL. Both\n // hooks are called unconditionally (rules of hooks); only one is invoked.\n const [createOrganization] = useCreateOrganizationMutation();\n const [createSellerOrganization] = useCreateSellerOrganizationMutation();\n const [createBillingAccountMutation] = useCreateBillingAccountMutation();\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const bus = useDevportalEventBus();\n\n // Multi-step status so the button/banner reflect the whole create flow —\n // not just the org-creation mutation's own loading flag, which flips back\n // to false before the (awaited) billing setup/link steps finish.\n const [phase, setPhase] = useState<SubmitPhase>(\"idle\");\n const isSubmitting = phase !== \"idle\";\n\n const [billingChoice, setBillingChoice] = useState<\"auto\" | \"existing\">(\n \"auto\",\n );\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useGetBillingAccountsByOrgQuery({\n fetchPolicy: \"cache-and-network\",\n context: { headers: { \"x-org-id\": tenantId ?? \"\" } },\n });\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"getBillingAccountsByOrg\"][number];\n const existingBillingAccounts: BillingAccount[] = useMemo(\n () => billingAccountsData?.getBillingAccountsByOrg ?? [],\n [billingAccountsData],\n );\n\n // Keep the \"existing account\" choice valid as the list loads: fall back to\n // auto-create if it turns out empty, and default-select once it arrives.\n useEffect(() => {\n if (billingChoice !== \"existing\" || billingAccountsLoading) return;\n if (existingBillingAccounts.length === 0) {\n setBillingChoice(\"auto\");\n return;\n }\n if (!selectedBillingAccountId) {\n setSelectedBillingAccountId(\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n }\n }, [\n billingChoice,\n billingAccountsLoading,\n existingBillingAccounts,\n selectedBillingAccountId,\n ]);\n\n const [formData, setFormData] = useState<CreateOrganizationFormData>({\n name: \"\",\n slug: \"\",\n description: \"\",\n websiteUrl: \"\",\n contactEmail: \"\",\n supportEmail: \"\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const generateSlug = (name: string): string => {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n };\n\n const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const name = e.target.value;\n setFormData((prev) => ({\n ...prev,\n name,\n slug: prev.slug || generateSlug(name),\n }));\n if (errors.name) {\n setErrors((prev) => ({ ...prev, name: undefined }));\n }\n };\n\n const handleChange = (\n field: keyof CreateOrganizationFormData,\n value: string,\n ) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n if (errors[field as keyof FormErrors]) {\n setErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n };\n\n const validate = (): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formData.name.trim()) {\n newErrors.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n } else if (formData.name.length < 2) {\n newErrors.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n } else if (formData.name.length > 100) {\n newErrors.name = tr(\n \"devportal.nameTooLong\",\n \"Name must be less than 100 characters\",\n );\n }\n\n if (!formData.slug.trim()) {\n newErrors.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n } else if (!/^[a-z0-9-]+$/.test(formData.slug)) {\n newErrors.slug = tr(\n \"devportal.slugInvalid\",\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n );\n }\n\n if (\n formData.contactEmail &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.contactEmail)\n ) {\n newErrors.contactEmail = tr(\n \"devportal.invalidEmailAddress\",\n \"Invalid email address\",\n );\n }\n\n if (\n formData.supportEmail &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.supportEmail)\n ) {\n newErrors.supportEmail = tr(\n \"devportal.invalidEmailAddress\",\n \"Invalid email address\",\n );\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validate()) return;\n\n setPhase(\"creating-org\");\n try {\n const input = {\n name: formData.name,\n slug: formData.slug || undefined,\n description: formData.description || undefined,\n websiteUrl: formData.websiteUrl || undefined,\n contactEmail: formData.contactEmail || undefined,\n supportEmail: formData.supportEmail || undefined,\n };\n\n const orgId = isSeller\n ? (await createSellerOrganization({ variables: { input } })).data\n ?.createSellerOrganization?.id\n : (await createOrganization({ variables: { input } })).data\n ?.createDeveloperOrganization?.id;\n\n if (!orgId) {\n setPhase(\"idle\");\n return;\n }\n\n bus.emit(\"devportal.org.created\", {\n organizationId: orgId,\n name: formData.name,\n });\n if (isSeller) {\n setActivePhysicalOrgId(orgId);\n } else {\n setActiveOrgId(orgId);\n }\n\n if (billingChoice === \"existing\" && selectedBillingAccountId) {\n setPhase(\"linking-billing\");\n try {\n await linkBillingAccount({\n variables: {\n organizationId: orgId,\n billingAccountId: selectedBillingAccountId,\n },\n });\n } catch {\n // non-blocking — can be linked later from the Revenue tab\n }\n } else {\n setPhase(\"setting-up-billing\");\n try {\n const billingResult = await createBillingAccountMutation({\n variables: {\n input: {\n name: formData.name,\n email: currentUser?.email ?? \"\",\n },\n },\n });\n const billingAccountId = billingResult.data?.createBillingAccount?.id;\n if (billingAccountId) {\n await linkBillingAccount({\n variables: { organizationId: orgId, billingAccountId },\n });\n }\n } catch {\n // non-blocking — can be linked later from the Revenue tab\n }\n }\n\n setPhase(\"redirecting\");\n handleNavigate(orgSectionPath(isSeller, orgId));\n } catch (error) {\n console.error(\"Failed to create organization:\", error);\n setPhase(\"idle\");\n }\n };\n\n const handleCancel = () => {\n handleNavigate(orgSectionPath(isSeller));\n };\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.createOrganization\", \"Create Organization\")}\n description={\n isSeller\n ? tr(\n \"devportal.createSellerOrganizationDescription\",\n \"Set up a seller organization to start selling physical products\",\n )\n : tr(\n \"devportal.createOrganizationDescription\",\n \"Set up a developer organization to collaborate with your team\",\n )\n }\n purpose={\n isSeller\n ? tr(\n \"devportal.createSellerOrganizationPurpose\",\n \"A seller organization is the shared owner of your physical listings, orders, and revenue. Create one here — you can invite members and complete legal/tax details afterwards.\",\n )\n : tr(\n \"devportal.createOrganizationPurpose\",\n \"An organization is the shared owner of your apps, members, and revenue. Create one here so your team works under a single identity — pick a name and tier now; you can invite members and verify it afterwards.\",\n )\n }\n backLink={`${basePath}${orgSectionPath(isSeller)}`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <form onSubmit={handleSubmit} className=\"space-y-8 max-w-3xl\">\n {/* Organization Details */}\n <PageSection\n title={tr(\"devportal.organizationDetails\", \"Organization Details\")}\n description={tr(\n \"devportal.organizationDetailsDescription\",\n \"Basic information about your organization\",\n )}\n >\n <div className=\"space-y-4\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={formData.name}\n onChange={handleNameChange}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={errors.name}\n hint={tr(\n \"devportal.organizationNameHint\",\n \"Your organization's display name\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={formData.slug}\n onChange={(e) =>\n handleChange(\"slug\", e.target.value.toLowerCase())\n }\n placeholder={tr(\"devportal.orgSlugPlaceholder\", \"acme-dev\")}\n required\n error={errors.slug}\n hint={tr(\n \"devportal.slugHint\",\n \"URL-friendly identifier (auto-generated from name)\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.description\", \"Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization...\",\n )}\n rows={3}\n />\n\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website URL\")}\n type=\"url\"\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder=\"https://example.com\"\n />\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.contactEmail\", \"Contact Email\")}\n type=\"email\"\n value={formData.contactEmail}\n onChange={(e) => handleChange(\"contactEmail\", e.target.value)}\n placeholder=\"contact@example.com\"\n error={errors.contactEmail}\n />\n\n <InputField\n label={tr(\"devportal.supportEmail\", \"Support Email\")}\n type=\"email\"\n value={formData.supportEmail}\n onChange={(e) => handleChange(\"supportEmail\", e.target.value)}\n placeholder=\"support@example.com\"\n error={errors.supportEmail}\n />\n </div>\n </div>\n </PageSection>\n\n {/* Billing Account */}\n <PageSection\n title={tr(\"devportal.billingAccount\", \"Billing Account\")}\n description={tr(\n \"devportal.billingAccountSectionDescription\",\n \"Revenue from sales will be credited here. You can change this anytime from the Revenue page.\",\n )}\n >\n <div className=\"space-y-3\">\n <button\n type=\"button\"\n onClick={() => setBillingChoice(\"auto\")}\n disabled={isSubmitting}\n className={cn(\n \"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n billingChoice === \"auto\"\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\n )}\n >\n <Check\n size={16}\n className={cn(\n \"mt-0.5 flex-shrink-0\",\n billingChoice === \"auto\"\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.billingAutoCreate\",\n \"Create a new billing account automatically\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {tr(\n \"devportal.billingAutoCreateHint\",\n \"We'll set one up using your organization name and account email. You can complete legal and tax details for payouts later in Organization Settings.\",\n )}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => setBillingChoice(\"existing\")}\n disabled={\n isSubmitting ||\n (!billingAccountsLoading &&\n existingBillingAccounts.length === 0)\n }\n className={cn(\n \"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n billingChoice === \"existing\"\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\n )}\n >\n <Check\n size={16}\n className={cn(\n \"mt-0.5 flex-shrink-0\",\n billingChoice === \"existing\"\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"flex items-center gap-1.5 text-sm font-medium\">\n <Link2 size={14} />\n {tr(\n \"devportal.billingLinkExisting\",\n \"Link an existing billing account\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {billingAccountsLoading\n ? tr(\n \"devportal.billingAccountsLoading\",\n \"Loading your billing accounts...\",\n )\n : existingBillingAccounts.length === 0\n ? tr(\n \"devportal.noBillingAccountsYet\",\n \"You don't have any billing accounts yet — create one from account billing settings first.\",\n )\n : tr(\n \"devportal.billingAccountsAvailable\",\n \"{{count}} billing account(s) available to link\",\n { count: existingBillingAccounts.length },\n )}\n </p>\n </div>\n </button>\n\n {billingChoice === \"existing\" &&\n existingBillingAccounts.length > 0 && (\n <div className=\"ml-8 space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n disabled={isSubmitting}\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 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\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=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.revenue.defaultAccount\",\n \"Default\",\n )}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n </PageSection>\n\n {/* Status while creating org + setting up billing */}\n {isSubmitting && (\n <div className=\"flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3 text-sm text-text-secondary\">\n <Loader2\n size={16}\n className=\"flex-shrink-0 animate-spin text-primary\"\n />\n {phase === \"creating-org\" &&\n tr(\n \"devportal.creatingOrgStatus\",\n \"Creating your organization...\",\n )}\n {phase === \"setting-up-billing\" &&\n tr(\n \"devportal.settingUpBillingStatus\",\n \"Setting up your billing account...\",\n )}\n {phase === \"linking-billing\" &&\n tr(\n \"devportal.linkingBillingStatus\",\n \"Linking your billing account...\",\n )}\n {phase === \"redirecting\" &&\n tr(\"devportal.redirectingStatus\", \"All set — redirecting...\")}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 border-t pt-6\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isSubmitting}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X size={16} />\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting}\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 disabled:opacity-50\"\n >\n {isSubmitting ? (\n <>\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n {phase === \"setting-up-billing\" &&\n tr(\"devportal.settingUpBilling\", \"Setting up billing...\")}\n {phase === \"linking-billing\" &&\n tr(\"devportal.linkingBilling\", \"Linking billing...\")}\n {(phase === \"creating-org\" || phase === \"redirecting\") &&\n tr(\"devportal.creating\", \"Creating...\")}\n </>\n ) : (\n <>\n <Building2 size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </>\n )}\n </button>\n </div>\n </form>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CreateOrganizationPage.js","names":["_Fragment","CreateOrganizationPage","useDevportal","isSeller","useIsSellerSection","tr","useTr","errors","setErrors","useState","submitError","setSubmitError","createOrganization","useCreateOrganizationMutation","createSellerOrganization","useCreateSellerOrganizationMutation","createBillingAccountMutation","useCreateBillingAccountMutation","linkBillingAccount","useLinkDevOrgBillingAccountMutation","bus","useDevportalEventBus","phase","setPhase","isSubmitting","billingChoice","setBillingChoice","selectedBillingAccountId","setSelectedBillingAccountId","billingAccountsData","billingAccountsLoading","useGetBillingAccountsByOrgQuery","tenantId","existingBillingAccounts","useMemo","a","formData","setFormData","handleNavigate","basePath","path","generateSlug","name","handleNameChange","prev","handleChange","field","value","validate","newErrors","PermissionGuard","PageLayout","orgSectionPath","input","orgId","setActivePhysicalOrgId","setActiveOrgId","billingAccountId","currentUser","error","errorMessage","PageSection","InputField","TextareaField","cn","Check","Link2","account","Loader2","X","Fragment","Building2"],"sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { X, Building2, Check, Link2, Loader2 } from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { InputField, TextareaField } from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport {\n useIsSellerSection,\n orgSectionPath,\n} from \"../hooks/useIsSellerSection\";\nimport {\n useCreateOrganizationMutation,\n useCreateSellerOrganizationMutation,\n useGetBillingAccountsByOrgQuery,\n useLinkDevOrgBillingAccountMutation,\n} from \"../../generated/global-operations\";\nimport { useCreateBillingAccountMutation } from \"../hooks\";\nimport { useDevportalEventBus } from \"../events\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\nimport { errorMessage } from \"../utils/errorMessage\";\n\ninterface CreateOrganizationFormData {\n name: string;\n slug: string;\n description: string;\n websiteUrl: string;\n contactEmail: string;\n supportEmail: string;\n}\n\ninterface FormErrors {\n name?: string;\n slug?: string;\n contactEmail?: string;\n supportEmail?: string;\n}\n\ntype SubmitPhase =\n | \"idle\"\n | \"creating-org\"\n | \"setting-up-billing\"\n | \"linking-billing\"\n | \"redirecting\";\n\n/**\n * Create new organization page — single step.\n * The user can either have a billing account auto-created and linked, or\n * link one of their existing billing accounts up front. Legal/tax details\n * are completed later from organization settings.\n */\nexport const CreateOrganizationPage: FC = () => {\n const {\n navigate,\n basePath,\n currentUser,\n tenantId,\n setActiveOrgId,\n setActivePhysicalOrgId,\n } = useDevportal();\n const isSeller = useIsSellerSection();\n const tr = useTr();\n const [errors, setErrors] = useState<FormErrors>({});\n // A failed save stays visible instead of silently resetting the form.\n const [submitError, setSubmitError] = useState<string | null>(null);\n // Shared page for both kinds — which mutation runs is the trust boundary\n // for DeveloperOrgKind (BOFF-7285): createSellerOrganization always makes\n // a PHYSICAL org, createDeveloperOrganization always makes DIGITAL. Both\n // hooks are called unconditionally (rules of hooks); only one is invoked.\n const [createOrganization] = useCreateOrganizationMutation();\n const [createSellerOrganization] = useCreateSellerOrganizationMutation();\n const [createBillingAccountMutation] = useCreateBillingAccountMutation();\n const [linkBillingAccount] = useLinkDevOrgBillingAccountMutation();\n const bus = useDevportalEventBus();\n\n // Multi-step status so the button/banner reflect the whole create flow —\n // not just the org-creation mutation's own loading flag, which flips back\n // to false before the (awaited) billing setup/link steps finish.\n const [phase, setPhase] = useState<SubmitPhase>(\"idle\");\n const isSubmitting = phase !== \"idle\";\n\n const [billingChoice, setBillingChoice] = useState<\"auto\" | \"existing\">(\n \"auto\",\n );\n const [selectedBillingAccountId, setSelectedBillingAccountId] = useState<\n string | null\n >(null);\n const { data: billingAccountsData, loading: billingAccountsLoading } =\n useGetBillingAccountsByOrgQuery({\n fetchPolicy: \"cache-and-network\",\n context: { headers: { \"x-org-id\": tenantId ?? \"\" } },\n });\n type BillingAccount = NonNullable<\n typeof billingAccountsData\n >[\"getBillingAccountsByOrg\"][number];\n const existingBillingAccounts: BillingAccount[] = useMemo(\n () => billingAccountsData?.getBillingAccountsByOrg ?? [],\n [billingAccountsData],\n );\n\n // Keep the \"existing account\" choice valid as the list loads: fall back to\n // auto-create if it turns out empty, and default-select once it arrives.\n useEffect(() => {\n if (billingChoice !== \"existing\" || billingAccountsLoading) return;\n if (existingBillingAccounts.length === 0) {\n setBillingChoice(\"auto\");\n return;\n }\n if (!selectedBillingAccountId) {\n setSelectedBillingAccountId(\n existingBillingAccounts.find((a) => a.isDefault)?.id ??\n existingBillingAccounts[0]?.id ??\n null,\n );\n }\n }, [\n billingChoice,\n billingAccountsLoading,\n existingBillingAccounts,\n selectedBillingAccountId,\n ]);\n\n const [formData, setFormData] = useState<CreateOrganizationFormData>({\n name: \"\",\n slug: \"\",\n description: \"\",\n websiteUrl: \"\",\n contactEmail: \"\",\n supportEmail: \"\",\n });\n\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const generateSlug = (name: string): string => {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n };\n\n const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const name = e.target.value;\n setFormData((prev) => ({\n ...prev,\n name,\n slug: prev.slug || generateSlug(name),\n }));\n if (errors.name) {\n setErrors((prev) => ({ ...prev, name: undefined }));\n }\n };\n\n const handleChange = (\n field: keyof CreateOrganizationFormData,\n value: string,\n ) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n if (errors[field as keyof FormErrors]) {\n setErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n };\n\n const validate = (): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formData.name.trim()) {\n newErrors.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n } else if (formData.name.length < 2) {\n newErrors.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n } else if (formData.name.length > 100) {\n newErrors.name = tr(\n \"devportal.nameTooLong\",\n \"Name must be less than 100 characters\",\n );\n }\n\n if (!formData.slug.trim()) {\n newErrors.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n } else if (!/^[a-z0-9-]+$/.test(formData.slug)) {\n newErrors.slug = tr(\n \"devportal.slugInvalid\",\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n );\n }\n\n if (\n formData.contactEmail &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.contactEmail)\n ) {\n newErrors.contactEmail = tr(\n \"devportal.invalidEmailAddress\",\n \"Invalid email address\",\n );\n }\n\n if (\n formData.supportEmail &&\n !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.supportEmail)\n ) {\n newErrors.supportEmail = tr(\n \"devportal.invalidEmailAddress\",\n \"Invalid email address\",\n );\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validate()) return;\n\n setSubmitError(null);\n setPhase(\"creating-org\");\n try {\n const input = {\n name: formData.name,\n slug: formData.slug || undefined,\n description: formData.description || undefined,\n websiteUrl: formData.websiteUrl || undefined,\n contactEmail: formData.contactEmail || undefined,\n supportEmail: formData.supportEmail || undefined,\n };\n\n const orgId = isSeller\n ? (await createSellerOrganization({ variables: { input } })).data\n ?.createSellerOrganization?.id\n : (await createOrganization({ variables: { input } })).data\n ?.createDeveloperOrganization?.id;\n\n if (!orgId) {\n setPhase(\"idle\");\n return;\n }\n\n bus.emit(\"devportal.org.created\", {\n organizationId: orgId,\n name: formData.name,\n });\n if (isSeller) {\n setActivePhysicalOrgId(orgId);\n } else {\n setActiveOrgId(orgId);\n }\n\n if (billingChoice === \"existing\" && selectedBillingAccountId) {\n setPhase(\"linking-billing\");\n try {\n await linkBillingAccount({\n variables: {\n organizationId: orgId,\n billingAccountId: selectedBillingAccountId,\n },\n });\n } catch {\n // non-blocking — can be linked later from the Revenue tab\n }\n } else {\n setPhase(\"setting-up-billing\");\n try {\n const billingResult = await createBillingAccountMutation({\n variables: {\n input: {\n name: formData.name,\n email: currentUser?.email ?? \"\",\n },\n },\n });\n const billingAccountId = billingResult.data?.createBillingAccount?.id;\n if (billingAccountId) {\n await linkBillingAccount({\n variables: { organizationId: orgId, billingAccountId },\n });\n }\n } catch {\n // non-blocking — can be linked later from the Revenue tab\n }\n }\n\n setPhase(\"redirecting\");\n handleNavigate(orgSectionPath(isSeller, orgId));\n } catch (error) {\n console.error(\"Failed to create organization:\", error);\n setSubmitError(\n errorMessage(\n error,\n tr(\n \"devportal.createOrganizationFailed\",\n \"We could not create your organization. Your details are still here, so you can try again.\",\n ),\n ),\n );\n setPhase(\"idle\");\n }\n };\n\n const handleCancel = () => {\n handleNavigate(orgSectionPath(isSeller));\n };\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.createOrganization\", \"Create Organization\")}\n description={\n isSeller\n ? tr(\n \"devportal.createSellerOrganizationDescription\",\n \"Set up a seller organization to start selling physical products\",\n )\n : tr(\n \"devportal.createOrganizationDescription\",\n \"Set up a developer organization to collaborate with your team\",\n )\n }\n purpose={\n isSeller\n ? tr(\n \"devportal.createSellerOrganizationPurpose\",\n \"A seller organization is the shared owner of your physical listings, orders, and revenue. Create one here — you can invite members and complete legal/tax details afterwards.\",\n )\n : tr(\n \"devportal.createOrganizationPurpose\",\n \"An organization is the shared owner of your apps, members, and revenue. Create one here so your team works under a single identity — pick a name and tier now; you can invite members and verify it afterwards.\",\n )\n }\n backLink={`${basePath}${orgSectionPath(isSeller)}`}\n backLabel={tr(\"devportal.backToOrganizations\", \"Back to Organizations\")}\n >\n <form onSubmit={handleSubmit} className=\"space-y-8 max-w-3xl\">\n {submitError && (\n <div\n role=\"alert\"\n className=\"rounded-md bg-status-error-bg px-3 py-2 text-sm text-status-error-text\"\n >\n {submitError}\n </div>\n )}\n {/* Organization Details */}\n <PageSection\n title={tr(\"devportal.organizationDetails\", \"Organization Details\")}\n description={tr(\n \"devportal.organizationDetailsDescription\",\n \"Basic information about your organization\",\n )}\n >\n <div className=\"space-y-4\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={formData.name}\n onChange={handleNameChange}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={errors.name}\n hint={tr(\n \"devportal.organizationNameHint\",\n \"Your organization's display name\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={formData.slug}\n onChange={(e) =>\n handleChange(\"slug\", e.target.value.toLowerCase())\n }\n placeholder={tr(\"devportal.orgSlugPlaceholder\", \"acme-dev\")}\n required\n error={errors.slug}\n hint={tr(\n \"devportal.slugHint\",\n \"URL-friendly identifier (auto-generated from name)\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.description\", \"Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization...\",\n )}\n rows={3}\n />\n\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website URL\")}\n type=\"url\"\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder=\"https://example.com\"\n />\n\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.contactEmail\", \"Contact Email\")}\n type=\"email\"\n value={formData.contactEmail}\n onChange={(e) => handleChange(\"contactEmail\", e.target.value)}\n placeholder=\"contact@example.com\"\n error={errors.contactEmail}\n />\n\n <InputField\n label={tr(\"devportal.supportEmail\", \"Support Email\")}\n type=\"email\"\n value={formData.supportEmail}\n onChange={(e) => handleChange(\"supportEmail\", e.target.value)}\n placeholder=\"support@example.com\"\n error={errors.supportEmail}\n />\n </div>\n </div>\n </PageSection>\n\n {/* Billing Account */}\n <PageSection\n title={tr(\"devportal.billingAccount\", \"Billing Account\")}\n description={tr(\n \"devportal.billingAccountSectionDescription\",\n \"Revenue from sales will be credited here. You can change this anytime from the Revenue page.\",\n )}\n >\n <div className=\"space-y-3\">\n <button\n type=\"button\"\n onClick={() => setBillingChoice(\"auto\")}\n disabled={isSubmitting}\n className={cn(\n \"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n billingChoice === \"auto\"\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\n )}\n >\n <Check\n size={16}\n className={cn(\n \"mt-0.5 flex-shrink-0\",\n billingChoice === \"auto\"\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium\">\n {tr(\n \"devportal.billingAutoCreate\",\n \"Create a new billing account automatically\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {tr(\n \"devportal.billingAutoCreateHint\",\n \"We'll set one up using your organization name and account email. You can complete legal and tax details for payouts later in Organization Settings.\",\n )}\n </p>\n </div>\n </button>\n\n <button\n type=\"button\"\n onClick={() => setBillingChoice(\"existing\")}\n disabled={\n isSubmitting ||\n (!billingAccountsLoading &&\n existingBillingAccounts.length === 0)\n }\n className={cn(\n \"flex w-full items-start gap-3 rounded-lg border px-4 py-3 text-left transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n billingChoice === \"existing\"\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\n )}\n >\n <Check\n size={16}\n className={cn(\n \"mt-0.5 flex-shrink-0\",\n billingChoice === \"existing\"\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <div className=\"flex-1 min-w-0\">\n <p className=\"flex items-center gap-1.5 text-sm font-medium\">\n <Link2 size={14} />\n {tr(\n \"devportal.billingLinkExisting\",\n \"Link an existing billing account\",\n )}\n </p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">\n {billingAccountsLoading\n ? tr(\n \"devportal.billingAccountsLoading\",\n \"Loading your billing accounts...\",\n )\n : existingBillingAccounts.length === 0\n ? tr(\n \"devportal.noBillingAccountsYet\",\n \"You don't have any billing accounts yet — create one from account billing settings first.\",\n )\n : tr(\n \"devportal.billingAccountsAvailable\",\n \"{{count}} billing account(s) available to link\",\n { count: existingBillingAccounts.length },\n )}\n </p>\n </div>\n </button>\n\n {billingChoice === \"existing\" &&\n existingBillingAccounts.length > 0 && (\n <div className=\"ml-8 space-y-2\">\n {existingBillingAccounts.map((account) => (\n <button\n key={account.id}\n type=\"button\"\n disabled={isSubmitting}\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 text-left text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50\",\n selectedBillingAccountId === account.id\n ? \"border-primary bg-action-primary-bg/5\"\n : \"border-border-subtle hover:bg-bg-sunken\",\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=\"min-w-0 flex-1\">\n <p className=\"truncate font-medium\">{account.name}</p>\n {account.isDefault && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.revenue.defaultAccount\",\n \"Default\",\n )}\n </p>\n )}\n </div>\n </button>\n ))}\n </div>\n )}\n </div>\n </PageSection>\n\n {/* Status while creating org + setting up billing */}\n {isSubmitting && (\n <div className=\"flex items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3 text-sm text-text-secondary\">\n <Loader2\n size={16}\n className=\"flex-shrink-0 animate-spin text-primary\"\n />\n {phase === \"creating-org\" &&\n tr(\n \"devportal.creatingOrgStatus\",\n \"Creating your organization...\",\n )}\n {phase === \"setting-up-billing\" &&\n tr(\n \"devportal.settingUpBillingStatus\",\n \"Setting up your billing account...\",\n )}\n {phase === \"linking-billing\" &&\n tr(\n \"devportal.linkingBillingStatus\",\n \"Linking your billing account...\",\n )}\n {phase === \"redirecting\" &&\n tr(\"devportal.redirectingStatus\", \"All set — redirecting...\")}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex items-center justify-end gap-3 border-t pt-6\">\n <button\n type=\"button\"\n onClick={handleCancel}\n disabled={isSubmitting}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n <X size={16} />\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting}\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 disabled:opacity-50\"\n >\n {isSubmitting ? (\n <>\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n {phase === \"setting-up-billing\" &&\n tr(\"devportal.settingUpBilling\", \"Setting up billing...\")}\n {phase === \"linking-billing\" &&\n tr(\"devportal.linkingBilling\", \"Linking billing...\")}\n {(phase === \"creating-org\" || phase === \"redirecting\") &&\n tr(\"devportal.creating\", \"Creating...\")}\n </>\n ) : (\n <>\n <Building2 size={16} />\n {tr(\"devportal.createOrganization\", \"Create Organization\")}\n </>\n )}\n </button>\n </div>\n </form>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|