@burdenoff/microfe-devportal 2026.713.9 → 2026.714.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.
@@ -1,19 +1,16 @@
1
1
  import { useDevportal as e } from "../providers/DevportalProvider.js";
2
- import { useDevportalEventBus as t } from "../events/index.js";
3
- import { useCreateApplicationMutation as n, useCreateBillingAccountMutation as r, useCreateOrganizationMutation as i } from "../../generated/global-operations.js";
4
- import { APP_TYPE_LABELS as a } from "../utils/constants.js";
5
- import { InputField as o, SelectField as s, TextareaField as c } from "../components/FormField.js";
2
+ import { cn as t } from "../utils/cn.js";
3
+ import { useDevportalEventBus as n } from "../events/index.js";
4
+ import { useCreateApplicationMutation as r, useCreateBillingAccountMutation as i, useCreateOrganizationMutation as a } from "../../generated/global-operations.js";
5
+ import { InputField as o, SelectField as ee, TextareaField as s } from "../components/FormField.js";
6
6
  import "../hooks/index.js";
7
- import { useState as l } from "react";
8
- import { useI18n as ee } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
- import { AppWindow as u, ArrowRight as te, BookOpen as d, Building2 as f, Check as p, ChevronRight as m, Key as ne, Rocket as h } from "lucide-react";
10
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
11
- import { Illustration as re, PagePurpose as v } from "@burdenoff/fe-libs/ui";
7
+ import { useState as c } from "react";
8
+ import { useI18n as l } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
9
+ import { AppWindow as u, ArrowRight as te, BookOpen as d, Box as ne, Building2 as f, Check as p, ChevronRight as m, GitFork as re, Key as h, Puzzle as g, Rocket as _ } from "lucide-react";
10
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
11
+ import { Illustration as ie, PagePurpose as ae } from "@burdenoff/fe-libs/ui";
12
12
  //#region src/devportal/pages/SetupPage.tsx
13
- var y = Object.entries(a).map(([e, t]) => ({
14
- value: e,
15
- label: t
16
- })), ie = [
13
+ var b = [
17
14
  {
18
15
  value: "productivity",
19
16
  label: "Productivity"
@@ -63,15 +60,15 @@ var y = Object.entries(a).map(([e, t]) => ({
63
60
  label: "Other"
64
61
  }
65
62
  ];
66
- function b(e) {
63
+ function x(e) {
67
64
  return e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
68
65
  }
69
- function x() {
66
+ function S() {
70
67
  try {
71
68
  localStorage.setItem("devportal_setup_dismissed", "1");
72
69
  } catch {}
73
70
  }
74
- var S = [
71
+ var C = [
75
72
  {
76
73
  key: "org",
77
74
  label: "Organization"
@@ -84,273 +81,317 @@ var S = [
84
81
  key: "done",
85
82
  label: "Done"
86
83
  }
87
- ], ae = ({ current: e }) => {
88
- let t = S.findIndex((t) => t.key === e);
89
- return /* @__PURE__ */ g("div", {
84
+ ], oe = ({ current: e }) => {
85
+ let t = C.findIndex((t) => t.key === e);
86
+ return /* @__PURE__ */ v("div", {
90
87
  className: "flex items-center gap-0",
91
- children: S.map((e, n) => {
88
+ children: C.map((e, n) => {
92
89
  let r = n < t, i = n === t;
93
- return /* @__PURE__ */ _("div", {
90
+ return /* @__PURE__ */ y("div", {
94
91
  className: "flex items-center",
95
- children: [/* @__PURE__ */ _("div", {
92
+ children: [/* @__PURE__ */ y("div", {
96
93
  className: "flex flex-col items-center gap-1.5",
97
- children: [/* @__PURE__ */ g("div", {
94
+ children: [/* @__PURE__ */ v("div", {
98
95
  className: ["flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold transition-colors", r ? "bg-action-primary-bg text-action-primary-text" : i ? "bg-action-primary-bg text-action-primary-text ring-4 ring-primary/20" : "bg-bg-sunken text-text-secondary"].join(" "),
99
- children: r ? /* @__PURE__ */ g(p, { size: 14 }) : n + 1
100
- }), /* @__PURE__ */ g("span", {
96
+ children: r ? /* @__PURE__ */ v(p, { size: 14 }) : n + 1
97
+ }), /* @__PURE__ */ v("span", {
101
98
  className: ["text-xs font-medium whitespace-nowrap", i ? "text-text-primary" : "text-text-secondary"].join(" "),
102
99
  children: e.label
103
100
  })]
104
- }), n < S.length - 1 && /* @__PURE__ */ g("div", { className: ["mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors", n < t ? "bg-action-primary-bg" : "bg-border"].join(" ") })]
101
+ }), n < C.length - 1 && /* @__PURE__ */ v("div", { className: ["mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors", n < t ? "bg-action-primary-bg" : "bg-border"].join(" ") })]
105
102
  }, e.key);
106
103
  })
107
104
  });
108
- }, C = () => {
109
- let { navigate: a, basePath: p, currentUser: S } = e(), { t: C } = ee(), T = t(), E = (e, t) => {
110
- let n = C(e);
105
+ }, w = () => {
106
+ let { navigate: t, basePath: p, currentUser: C } = e(), { t: w } = l(), D = n(), O = (e, t) => {
107
+ let n = w(e);
111
108
  return n === e ? t : n;
112
- }, D = (e) => a?.(`${p}${e}`), [O, k] = l("org"), [A, oe] = l(null), [j, M] = l(null), [N, se] = l(""), [P, F] = l(""), [I, L] = l(""), [R, z] = l({}), [B, { loading: V }] = i(), [H] = r(), U = () => {
109
+ }, k = (e) => t?.(`${p}${e}`), [A, j] = c("org"), [M, se] = c(null), [N, ce] = c(null), [P, le] = c(""), [F, I] = c(""), [L, R] = c(""), [z, B] = c({}), [V, { loading: H }] = a(), [U] = i(), ue = () => {
113
110
  let e = {};
114
- return N.trim() ? N.length < 2 && (e.name = E("devportal.orgNameTooShort", "Name must be at least 2 characters")) : e.name = E("devportal.orgNameRequired", "Organization name is required"), P.trim() ? /^[a-z0-9-]+$/.test(P) || (e.slug = E("devportal.slugInvalid", "Lowercase letters, numbers, and hyphens only")) : e.slug = E("devportal.slugRequired", "Slug is required"), z(e), Object.keys(e).length === 0;
115
- }, W = async () => {
116
- if (U()) try {
117
- let e = (await B({ variables: { input: {
118
- name: N,
119
- slug: P || void 0,
120
- description: I || void 0
111
+ return P.trim() ? P.length < 2 && (e.name = O("devportal.orgNameTooShort", "Name must be at least 2 characters")) : e.name = O("devportal.orgNameRequired", "Organization name is required"), F.trim() ? /^[a-z0-9-]+$/.test(F) || (e.slug = O("devportal.slugInvalid", "Lowercase letters, numbers, and hyphens only")) : e.slug = O("devportal.slugRequired", "Slug is required"), B(e), Object.keys(e).length === 0;
112
+ }, de = async () => {
113
+ if (ue()) try {
114
+ let e = (await V({ variables: { input: {
115
+ name: P,
116
+ slug: F || void 0,
117
+ description: L || void 0
121
118
  } } })).data?.createDeveloperOrganization?.id;
122
119
  if (e) {
123
- T.emit("devportal.org.created", {
120
+ D.emit("devportal.org.created", {
124
121
  organizationId: e,
125
- name: N
126
- }), oe(e);
122
+ name: P
123
+ }), se(e);
127
124
  try {
128
- H({ variables: { input: {
129
- name: N,
130
- email: S?.email ?? ""
125
+ U({ variables: { input: {
126
+ name: P,
127
+ email: C?.email ?? ""
131
128
  } } }).catch(() => {});
132
129
  } catch {}
133
- k("app");
130
+ j("app");
134
131
  }
135
132
  } catch {}
136
- }, [G, ce] = l(""), [K, le] = l(""), [q, ue] = l(""), [J, de] = l(""), [Y, fe] = l(""), [X, Z] = l({}), [pe, { loading: Q }] = n(), me = () => {
133
+ }, [W, fe] = c(""), [G, pe] = c(""), [K, q] = c(null), [J, me] = c(""), [Y, he] = c(""), [X, Z] = c({}), [ge, { loading: Q }] = r(), _e = () => K === "node" ? "NODE" : K === "workflow" ? "WORKFLOW" : "API_INTEGRATION", ve = () => {
137
134
  let e = {};
138
- return G.trim() ? G.length < 3 && (e.name = E("devportal.nameTooShort", "Name must be at least 3 characters")) : e.name = E("devportal.appNameRequired", "Application name is required"), q || (e.appType = E("devportal.appTypeRequired", "Application type is required")), J || (e.category = E("devportal.categoryRequired", "Category is required")), Y.trim() || (e.shortDescription = E("devportal.shortDescriptionRequired", "Short description is required")), Z(e), Object.keys(e).length === 0;
139
- }, he = async () => {
140
- if (me()) try {
141
- let e = (await pe({ variables: { input: {
142
- name: G,
143
- slug: K || void 0,
144
- appType: q,
135
+ return W.trim() ? W.length < 3 && (e.name = O("devportal.nameTooShort", "Name must be at least 3 characters")) : e.name = O("devportal.appNameRequired", "Application name is required"), K || (e.builderType = O("devportal.appTypeRequired", "Application type is required")), J || (e.category = O("devportal.categoryRequired", "Category is required")), Y.trim() || (e.shortDescription = O("devportal.shortDescriptionRequired", "Short description is required")), Z(e), Object.keys(e).length === 0;
136
+ }, ye = async () => {
137
+ if (!ve()) return;
138
+ let e = _e();
139
+ try {
140
+ let t = (await ge({ variables: { input: {
141
+ name: W,
142
+ slug: G || void 0,
143
+ appType: e,
145
144
  category: J || void 0,
146
145
  shortDescription: Y || void 0,
147
146
  visibility: "PRIVATE",
148
- developerOrganizationId: A || void 0
147
+ developerOrganizationId: M || void 0
149
148
  } } })).data?.createApplication?.id;
150
- e && (T.emit("devportal.app.created", {
151
- appId: e,
152
- name: G,
153
- appType: q,
154
- organizationId: A
155
- }), M(e), x(), k("done"));
149
+ t && (D.emit("devportal.app.created", {
150
+ appId: t,
151
+ name: W,
152
+ appType: e,
153
+ organizationId: M
154
+ }), ce(t), S(), j("done"));
156
155
  } catch {}
157
156
  }, $ = () => {
158
- x(), D("/");
157
+ S(), k("/");
159
158
  };
160
- return /* @__PURE__ */ _("main", {
159
+ return /* @__PURE__ */ y("main", {
161
160
  className: "min-h-screen bg-surface-default",
162
- children: [/* @__PURE__ */ g("div", {
161
+ children: [/* @__PURE__ */ v("div", {
163
162
  className: "border-b border-border-default bg-surface-raised",
164
- children: /* @__PURE__ */ g("div", {
163
+ children: /* @__PURE__ */ v("div", {
165
164
  className: "mx-auto max-w-2xl px-6 py-5",
166
- children: /* @__PURE__ */ _("div", {
165
+ children: /* @__PURE__ */ y("div", {
167
166
  className: "flex items-center justify-between",
168
- children: [/* @__PURE__ */ _("div", {
167
+ children: [/* @__PURE__ */ y("div", {
169
168
  className: "flex items-center gap-3",
170
- children: [/* @__PURE__ */ g("div", {
169
+ children: [/* @__PURE__ */ v("div", {
171
170
  className: "flex h-9 w-9 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary",
172
- children: /* @__PURE__ */ g(h, { size: 20 })
173
- }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("p", {
171
+ children: /* @__PURE__ */ v(_, { size: 20 })
172
+ }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
174
173
  className: "text-xs font-medium text-text-secondary",
175
- children: E("devportal.developerPortal", "Developer Portal")
176
- }), /* @__PURE__ */ g("h1", {
174
+ children: O("devportal.developerPortal", "Developer Portal")
175
+ }), /* @__PURE__ */ v("h1", {
177
176
  className: "text-base font-semibold text-text-primary",
178
- children: E("devportal.setup.title", "Get set up")
177
+ children: O("devportal.setup.title", "Get set up")
179
178
  })] })]
180
- }), O !== "done" && /* @__PURE__ */ g("button", {
179
+ }), A !== "done" && /* @__PURE__ */ v("button", {
181
180
  type: "button",
182
181
  onClick: $,
183
182
  className: "text-sm text-text-secondary hover:text-text-primary transition-colors",
184
- children: E("devportal.setup.skipForNow", "Skip for now")
183
+ children: O("devportal.setup.skipForNow", "Skip for now")
185
184
  })]
186
185
  })
187
186
  })
188
- }), /* @__PURE__ */ _("div", {
187
+ }), /* @__PURE__ */ y("div", {
189
188
  className: "mx-auto max-w-2xl px-6 py-10",
190
189
  children: [
191
- /* @__PURE__ */ g("div", {
190
+ /* @__PURE__ */ v("div", {
192
191
  className: "mb-10 flex justify-center",
193
- children: /* @__PURE__ */ g(ae, { current: O })
192
+ children: /* @__PURE__ */ v(oe, { current: A })
194
193
  }),
195
- O === "org" && /* @__PURE__ */ _("div", {
194
+ A === "org" && /* @__PURE__ */ y("div", {
196
195
  className: "mb-8 flex flex-col items-center gap-3 text-center",
197
- children: [/* @__PURE__ */ g(re, {
196
+ children: [/* @__PURE__ */ v(ie, {
198
197
  name: "onboarding",
199
- alt: E("devportal.setup.illustrationAlt", "Getting started with the developer portal"),
198
+ alt: O("devportal.setup.illustrationAlt", "Getting started with the developer portal"),
200
199
  size: "md"
201
- }), /* @__PURE__ */ g(v, {
200
+ }), /* @__PURE__ */ v(ae, {
202
201
  className: "justify-center",
203
- children: E("devportal.setup.purpose", "Two quick steps to start building: create the organization that owns your apps, then register your first app. You can change everything later — this just gets you to a working starting point.")
202
+ children: O("devportal.setup.purpose", "Two quick steps to start building: create the organization that owns your apps, then register your first app. You can change everything later — this just gets you to a working starting point.")
204
203
  })]
205
204
  }),
206
- O === "org" && /* @__PURE__ */ _("div", {
205
+ A === "org" && /* @__PURE__ */ y("div", {
207
206
  className: "rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm",
208
207
  children: [
209
- /* @__PURE__ */ _("div", {
208
+ /* @__PURE__ */ y("div", {
210
209
  className: "mb-6 flex items-center gap-3",
211
- children: [/* @__PURE__ */ g("div", {
210
+ children: [/* @__PURE__ */ v("div", {
212
211
  className: "flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary",
213
- children: /* @__PURE__ */ g(f, { size: 20 })
214
- }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h2", {
212
+ children: /* @__PURE__ */ v(f, { size: 20 })
213
+ }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h2", {
215
214
  className: "text-lg font-semibold text-text-primary",
216
- children: E("devportal.setup.orgTitle", "Set up your organization")
217
- }), /* @__PURE__ */ g("p", {
215
+ children: O("devportal.setup.orgTitle", "Set up your organization")
216
+ }), /* @__PURE__ */ v("p", {
218
217
  className: "text-sm text-text-secondary",
219
- children: E("devportal.setup.orgSubtitle", "This groups your apps and teams under one publisher identity.")
218
+ children: O("devportal.setup.orgSubtitle", "This groups your apps and teams under one publisher identity.")
220
219
  })] })]
221
220
  }),
222
- /* @__PURE__ */ _("div", {
221
+ /* @__PURE__ */ y("div", {
223
222
  className: "space-y-5",
224
223
  children: [
225
- /* @__PURE__ */ g(o, {
226
- label: E("devportal.organizationName", "Organization Name"),
227
- value: N,
224
+ /* @__PURE__ */ v(o, {
225
+ label: O("devportal.organizationName", "Organization Name"),
226
+ value: P,
228
227
  onChange: (e) => {
229
- se(e.target.value), (!P || P === b(N)) && F(b(e.target.value)), z((e) => ({
228
+ le(e.target.value), (!F || F === x(P)) && I(x(e.target.value)), B((e) => ({
230
229
  ...e,
231
230
  name: void 0
232
231
  }));
233
232
  },
234
- placeholder: E("devportal.organizationNamePlaceholder", "Acme Development"),
233
+ placeholder: O("devportal.organizationNamePlaceholder", "Acme Development"),
235
234
  required: !0,
236
- error: R.name
235
+ error: z.name
237
236
  }),
238
- /* @__PURE__ */ g(o, {
239
- label: E("devportal.slug", "Slug"),
240
- value: P,
237
+ /* @__PURE__ */ v(o, {
238
+ label: O("devportal.slug", "Slug"),
239
+ value: F,
241
240
  onChange: (e) => {
242
- F(e.target.value.toLowerCase()), z((e) => ({
241
+ I(e.target.value.toLowerCase()), B((e) => ({
243
242
  ...e,
244
243
  slug: void 0
245
244
  }));
246
245
  },
247
246
  placeholder: "acme-dev",
248
247
  required: !0,
249
- error: R.slug,
250
- hint: E("devportal.slugHint", "URL-friendly identifier — auto-generated from name")
248
+ error: z.slug,
249
+ hint: O("devportal.slugHint", "URL-friendly identifier — auto-generated from name")
251
250
  }),
252
- /* @__PURE__ */ g(c, {
253
- label: E("devportal.description", "Description"),
254
- value: I,
255
- onChange: (e) => L(e.target.value),
256
- placeholder: E("devportal.orgDescriptionPlaceholder", "Tell us about your organization…"),
251
+ /* @__PURE__ */ v(s, {
252
+ label: O("devportal.description", "Description"),
253
+ value: L,
254
+ onChange: (e) => R(e.target.value),
255
+ placeholder: O("devportal.orgDescriptionPlaceholder", "Tell us about your organization…"),
257
256
  rows: 2
258
257
  })
259
258
  ]
260
259
  }),
261
- /* @__PURE__ */ _("div", {
260
+ /* @__PURE__ */ y("div", {
262
261
  className: "mt-8 flex items-center justify-between border-t border-border-default pt-6",
263
- children: [/* @__PURE__ */ g("button", {
262
+ children: [/* @__PURE__ */ v("button", {
264
263
  type: "button",
265
264
  onClick: $,
266
265
  className: "text-sm text-text-secondary hover:text-text-primary transition-colors",
267
- children: E("devportal.setup.skipForNow", "Skip for now")
268
- }), /* @__PURE__ */ _("button", {
266
+ children: O("devportal.setup.skipForNow", "Skip for now")
267
+ }), /* @__PURE__ */ y("button", {
269
268
  type: "button",
270
- onClick: () => void W(),
271
- disabled: V,
269
+ onClick: () => void de(),
270
+ disabled: H,
272
271
  className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors",
273
272
  children: [
274
- V ? /* @__PURE__ */ g("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : null,
275
- E("devportal.setup.createAndContinue", "Create & Continue"),
276
- !V && /* @__PURE__ */ g(m, { size: 16 })
273
+ H ? /* @__PURE__ */ v("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : null,
274
+ O("devportal.setup.createAndContinue", "Create & Continue"),
275
+ !H && /* @__PURE__ */ v(m, { size: 16 })
277
276
  ]
278
277
  })]
279
278
  })
280
279
  ]
281
280
  }),
282
- O === "app" && /* @__PURE__ */ _("div", {
281
+ A === "app" && /* @__PURE__ */ y("div", {
283
282
  className: "rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm",
284
283
  children: [
285
- /* @__PURE__ */ _("div", {
284
+ /* @__PURE__ */ y("div", {
286
285
  className: "mb-6 flex items-center gap-3",
287
- children: [/* @__PURE__ */ g("div", {
286
+ children: [/* @__PURE__ */ v("div", {
288
287
  className: "flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary",
289
- children: /* @__PURE__ */ g(u, { size: 20 })
290
- }), /* @__PURE__ */ _("div", { children: [/* @__PURE__ */ g("h2", {
288
+ children: /* @__PURE__ */ v(u, { size: 20 })
289
+ }), /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("h2", {
291
290
  className: "text-lg font-semibold text-text-primary",
292
- children: E("devportal.setup.appTitle", "Create your first app")
293
- }), /* @__PURE__ */ g("p", {
291
+ children: O("devportal.setup.appTitle", "Create your first app")
292
+ }), /* @__PURE__ */ v("p", {
294
293
  className: "text-sm text-text-secondary",
295
- children: E("devportal.setup.appSubtitle", "Register the app you want to publish or integrate.")
294
+ children: O("devportal.setup.appSubtitle", "Register the app you want to publish or integrate.")
296
295
  })] })]
297
296
  }),
298
- /* @__PURE__ */ _("div", {
297
+ /* @__PURE__ */ y("div", {
299
298
  className: "space-y-5",
300
299
  children: [
301
- /* @__PURE__ */ g(o, {
302
- label: E("devportal.applicationName", "Application Name"),
303
- value: G,
300
+ /* @__PURE__ */ v(o, {
301
+ label: O("devportal.applicationName", "Application Name"),
302
+ value: W,
304
303
  onChange: (e) => {
305
- ce(e.target.value), (!K || K === b(G)) && le(b(e.target.value)), Z((e) => ({
304
+ fe(e.target.value), (!G || G === x(W)) && pe(x(e.target.value)), Z((e) => ({
306
305
  ...e,
307
306
  name: void 0
308
307
  }));
309
308
  },
310
- placeholder: E("devportal.applicationNamePlaceholder", "My Awesome App"),
309
+ placeholder: O("devportal.applicationNamePlaceholder", "My Awesome App"),
311
310
  required: !0,
312
311
  error: X.name
313
312
  }),
314
- /* @__PURE__ */ _("div", {
315
- className: "grid grid-cols-2 gap-4",
316
- children: [/* @__PURE__ */ g(s, {
317
- label: E("devportal.applicationType", "Application Type"),
318
- value: q,
319
- onChange: (e) => {
320
- ue(e.target.value), Z((e) => ({
321
- ...e,
322
- appType: void 0
323
- }));
324
- },
325
- options: y,
326
- placeholder: E("devportal.selectType", "Select type…"),
327
- required: !0,
328
- error: X.appType
329
- }), /* @__PURE__ */ g(s, {
330
- label: E("devportal.category", "Category"),
331
- value: J,
332
- onChange: (e) => {
333
- de(e.target.value), Z((e) => ({
334
- ...e,
335
- category: void 0
336
- }));
337
- },
338
- options: ie,
339
- placeholder: E("devportal.selectCategory", "Select category…"),
340
- required: !0,
341
- error: X.category
342
- })]
313
+ /* @__PURE__ */ y("div", { children: [
314
+ /* @__PURE__ */ y("p", {
315
+ className: "mb-2 text-sm font-medium text-text-primary",
316
+ children: [
317
+ O("devportal.applicationType", "Application Type"),
318
+ " ",
319
+ /* @__PURE__ */ v("span", {
320
+ className: "text-status-error-text",
321
+ children: "*"
322
+ })
323
+ ]
324
+ }),
325
+ /* @__PURE__ */ y("div", {
326
+ className: "grid grid-cols-3 gap-3",
327
+ children: [
328
+ /* @__PURE__ */ v(T, {
329
+ icon: ne,
330
+ title: "App",
331
+ description: "OAuth integration for the platform",
332
+ selected: K === "app",
333
+ onClick: () => {
334
+ q("app"), Z((e) => ({
335
+ ...e,
336
+ builderType: void 0
337
+ }));
338
+ }
339
+ }),
340
+ /* @__PURE__ */ v(T, {
341
+ icon: g,
342
+ title: "Node",
343
+ description: "Custom FluidGrids workflow node",
344
+ selected: K === "node",
345
+ onClick: () => {
346
+ q("node"), Z((e) => ({
347
+ ...e,
348
+ builderType: void 0
349
+ }));
350
+ }
351
+ }),
352
+ /* @__PURE__ */ v(T, {
353
+ icon: re,
354
+ title: "Workflow",
355
+ description: "Reusable automation template",
356
+ selected: K === "workflow",
357
+ onClick: () => {
358
+ q("workflow"), Z((e) => ({
359
+ ...e,
360
+ builderType: void 0
361
+ }));
362
+ }
363
+ })
364
+ ]
365
+ }),
366
+ X.builderType && /* @__PURE__ */ v("p", {
367
+ className: "mt-1.5 text-xs text-status-error-text",
368
+ children: X.builderType
369
+ })
370
+ ] }),
371
+ /* @__PURE__ */ v(ee, {
372
+ label: O("devportal.category", "Category"),
373
+ value: J,
374
+ onChange: (e) => {
375
+ me(e.target.value), Z((e) => ({
376
+ ...e,
377
+ category: void 0
378
+ }));
379
+ },
380
+ options: b,
381
+ placeholder: O("devportal.selectCategory", "Select category…"),
382
+ required: !0,
383
+ error: X.category
343
384
  }),
344
- /* @__PURE__ */ g(c, {
345
- label: E("devportal.shortDescription", "Short Description"),
385
+ /* @__PURE__ */ v(s, {
386
+ label: O("devportal.shortDescription", "Short Description"),
346
387
  value: Y,
347
388
  onChange: (e) => {
348
- fe(e.target.value), Z((e) => ({
389
+ he(e.target.value), Z((e) => ({
349
390
  ...e,
350
391
  shortDescription: void 0
351
392
  }));
352
393
  },
353
- placeholder: E("devportal.shortDescriptionPlaceholder", "A brief description of what your app does"),
394
+ placeholder: O("devportal.shortDescriptionPlaceholder", "A brief description of what your app does"),
354
395
  required: !0,
355
396
  error: X.shortDescription,
356
397
  rows: 2,
@@ -358,109 +399,133 @@ var S = [
358
399
  })
359
400
  ]
360
401
  }),
361
- /* @__PURE__ */ _("div", {
402
+ /* @__PURE__ */ y("div", {
362
403
  className: "mt-8 flex items-center justify-between border-t border-border-default pt-6",
363
- children: [/* @__PURE__ */ g("button", {
404
+ children: [/* @__PURE__ */ v("button", {
364
405
  type: "button",
365
406
  onClick: $,
366
407
  className: "text-sm text-text-secondary hover:text-text-primary transition-colors",
367
- children: E("devportal.setup.skipForNow", "Skip for now")
368
- }), /* @__PURE__ */ _("button", {
408
+ children: O("devportal.setup.skipForNow", "Skip for now")
409
+ }), /* @__PURE__ */ y("button", {
369
410
  type: "button",
370
- onClick: () => void he(),
411
+ onClick: () => void ye(),
371
412
  disabled: Q,
372
413
  className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors",
373
414
  children: [
374
- Q ? /* @__PURE__ */ g("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : null,
375
- E("devportal.setup.createApp", "Create App"),
376
- !Q && /* @__PURE__ */ g(m, { size: 16 })
415
+ Q ? /* @__PURE__ */ v("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }) : null,
416
+ O("devportal.setup.createApp", "Create App"),
417
+ !Q && /* @__PURE__ */ v(m, { size: 16 })
377
418
  ]
378
419
  })]
379
420
  })
380
421
  ]
381
422
  }),
382
- O === "done" && /* @__PURE__ */ _("div", {
423
+ A === "done" && /* @__PURE__ */ y("div", {
383
424
  className: "text-center",
384
425
  children: [
385
- /* @__PURE__ */ g("div", {
426
+ /* @__PURE__ */ v("div", {
386
427
  className: "mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-action-primary-bg/10 text-primary",
387
- children: /* @__PURE__ */ g(h, { size: 32 })
428
+ children: /* @__PURE__ */ v(_, { size: 32 })
388
429
  }),
389
- /* @__PURE__ */ g("h2", {
430
+ /* @__PURE__ */ v("h2", {
390
431
  className: "text-2xl font-bold text-text-primary",
391
- children: E("devportal.setup.doneTitle", "You're all set!")
432
+ children: O("devportal.setup.doneTitle", "You're all set!")
392
433
  }),
393
- /* @__PURE__ */ g("p", {
434
+ /* @__PURE__ */ v("p", {
394
435
  className: "mt-2 text-text-secondary",
395
- children: E("devportal.setup.doneSubtitle", "Your organization and first app are ready. Here's what to do next.")
436
+ children: O("devportal.setup.doneSubtitle", "Your organization and first app are ready. Here's what to do next.")
396
437
  }),
397
- /* @__PURE__ */ _("div", {
438
+ /* @__PURE__ */ y("div", {
398
439
  className: "mt-8 grid gap-3 sm:grid-cols-2",
399
440
  children: [
400
- j && /* @__PURE__ */ g(w, {
401
- icon: /* @__PURE__ */ g(u, { size: 20 }),
402
- title: E("devportal.setup.viewApp", "View your app"),
403
- description: E("devportal.setup.viewAppDesc", "Configure OAuth, webhooks, and versioning"),
404
- onClick: () => D(`/apps/${j}`),
441
+ N && /* @__PURE__ */ v(E, {
442
+ icon: /* @__PURE__ */ v(u, { size: 20 }),
443
+ title: O("devportal.setup.viewApp", "View your app"),
444
+ description: O("devportal.setup.viewAppDesc", "Configure OAuth, webhooks, and versioning"),
445
+ onClick: () => k(`/apps/${N}`),
405
446
  primary: !0
406
447
  }),
407
- /* @__PURE__ */ g(w, {
408
- icon: /* @__PURE__ */ g(ne, { size: 20 }),
409
- title: E("devportal.setup.generateApiKey", "Generate API key"),
410
- description: E("devportal.setup.generateApiKeyDesc", "Create credentials to start calling APIs"),
411
- onClick: () => D("/api-keys/new")
448
+ /* @__PURE__ */ v(E, {
449
+ icon: /* @__PURE__ */ v(h, { size: 20 }),
450
+ title: O("devportal.setup.generateApiKey", "Generate API key"),
451
+ description: O("devportal.setup.generateApiKeyDesc", "Create credentials to start calling APIs"),
452
+ onClick: () => k("/api-keys/new")
412
453
  }),
413
- /* @__PURE__ */ g(w, {
414
- icon: /* @__PURE__ */ g(d, { size: 20 }),
415
- title: E("devportal.setup.browseDocs", "Browse docs"),
416
- description: E("devportal.setup.browseDocsDesc", "Learn about publishing, SDKs, and webhooks"),
417
- onClick: () => D("/docs")
454
+ /* @__PURE__ */ v(E, {
455
+ icon: /* @__PURE__ */ v(d, { size: 20 }),
456
+ title: O("devportal.setup.browseDocs", "Browse docs"),
457
+ description: O("devportal.setup.browseDocsDesc", "Learn about publishing, SDKs, and webhooks"),
458
+ onClick: () => k("/docs")
418
459
  }),
419
- A && /* @__PURE__ */ g(w, {
420
- icon: /* @__PURE__ */ g(f, { size: 20 }),
421
- title: E("devportal.setup.inviteTeam", "Invite your team"),
422
- description: E("devportal.setup.inviteTeamDesc", "Add members to collaborate on your apps"),
423
- onClick: () => D(`/organizations/${A}/members`)
460
+ M && /* @__PURE__ */ v(E, {
461
+ icon: /* @__PURE__ */ v(f, { size: 20 }),
462
+ title: O("devportal.setup.inviteTeam", "Invite your team"),
463
+ description: O("devportal.setup.inviteTeamDesc", "Add members to collaborate on your apps"),
464
+ onClick: () => k(`/organizations/${M}/members`)
424
465
  })
425
466
  ]
426
467
  }),
427
- /* @__PURE__ */ _("button", {
468
+ /* @__PURE__ */ y("button", {
428
469
  type: "button",
429
- onClick: () => D("/"),
470
+ onClick: () => k("/"),
430
471
  className: "mt-8 inline-flex items-center gap-2 text-sm text-text-secondary hover:text-text-primary transition-colors",
431
- children: [E("devportal.setup.goToDashboard", "Go to dashboard"), /* @__PURE__ */ g(te, { size: 14 })]
472
+ children: [O("devportal.setup.goToDashboard", "Go to dashboard"), /* @__PURE__ */ v(te, { size: 14 })]
432
473
  })
433
474
  ]
434
475
  })
435
476
  ]
436
477
  })]
437
478
  });
438
- }, w = ({ icon: e, title: t, description: n, onClick: r, primary: i }) => /* @__PURE__ */ _("button", {
479
+ }, T = ({ icon: e, title: n, description: r, selected: i, onClick: a }) => /* @__PURE__ */ y("button", {
480
+ type: "button",
481
+ onClick: a,
482
+ className: t("relative flex flex-col gap-2 rounded-xl border-2 p-4 text-left transition-all hover:border-primary/50 hover:shadow-sm", i ? "border-primary bg-action-primary-bg/5 shadow-sm" : "border-border-subtle bg-bg-surface"),
483
+ children: [
484
+ i && /* @__PURE__ */ v("span", {
485
+ className: "absolute top-3 right-3 flex h-4 w-4 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text",
486
+ children: /* @__PURE__ */ v(p, { size: 10 })
487
+ }),
488
+ /* @__PURE__ */ v("div", {
489
+ className: "flex h-8 w-8 items-center justify-center rounded-lg bg-bg-sunken",
490
+ children: /* @__PURE__ */ v(e, {
491
+ size: 18,
492
+ className: "text-text-primary"
493
+ })
494
+ }),
495
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
496
+ className: "text-sm font-semibold text-text-primary",
497
+ children: n
498
+ }), /* @__PURE__ */ v("p", {
499
+ className: "mt-0.5 text-xs text-text-secondary",
500
+ children: r
501
+ })] })
502
+ ]
503
+ }), E = ({ icon: e, title: t, description: n, onClick: r, primary: i }) => /* @__PURE__ */ y("button", {
439
504
  type: "button",
440
505
  onClick: r,
441
506
  className: ["flex items-start gap-4 rounded-xl border p-5 text-left transition-colors", i ? "border-primary bg-action-primary-bg/5 hover:bg-action-primary-bg/10" : "border-border-default bg-surface-raised hover:bg-surface-hover"].join(" "),
442
507
  children: [
443
- /* @__PURE__ */ g("div", {
508
+ /* @__PURE__ */ v("div", {
444
509
  className: ["flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg", i ? "bg-action-primary-bg/20 text-primary" : "bg-bg-sunken text-text-secondary"].join(" "),
445
510
  children: e
446
511
  }),
447
- /* @__PURE__ */ _("div", {
512
+ /* @__PURE__ */ y("div", {
448
513
  className: "min-w-0 flex-1",
449
- children: [/* @__PURE__ */ g("p", {
514
+ children: [/* @__PURE__ */ v("p", {
450
515
  className: "font-semibold text-text-primary",
451
516
  children: t
452
- }), /* @__PURE__ */ g("p", {
517
+ }), /* @__PURE__ */ v("p", {
453
518
  className: "mt-0.5 text-sm text-text-secondary",
454
519
  children: n
455
520
  })]
456
521
  }),
457
- /* @__PURE__ */ g(m, {
522
+ /* @__PURE__ */ v(m, {
458
523
  size: 16,
459
524
  className: "mt-0.5 flex-shrink-0 text-text-secondary"
460
525
  })
461
526
  ]
462
527
  });
463
528
  //#endregion
464
- export { C as SetupPage };
529
+ export { w as SetupPage };
465
530
 
466
531
  //# sourceMappingURL=SetupPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SetupPage.js","names":[],"sources":["../../../src/devportal/pages/SetupPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n ArrowRight,\n Building2,\n AppWindow,\n Rocket,\n Check,\n Key,\n BookOpen,\n ChevronRight,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { Illustration, PagePurpose } from \"@burdenoff/fe-libs/ui\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useDevportalEventBus } from \"../events\";\nimport type { AppType } from \"../types\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useCreateOrganizationMutation,\n useCreateApplicationMutation,\n} from \"../../generated/global-operations\";\nimport { useCreateBillingAccountMutation } from \"../hooks\";\n\ntype SetupStep = \"org\" | \"app\" | \"done\";\n\nconst APP_TYPE_OPTIONS = Object.entries(APP_TYPE_LABELS).map(\n ([value, label]) => ({\n value,\n label,\n }),\n);\n\nconst CATEGORY_OPTIONS = [\n { value: \"productivity\", label: \"Productivity\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"automation\", label: \"Automation\" },\n { value: \"developer-tools\", label: \"Developer Tools\" },\n { value: \"finance\", label: \"Finance\" },\n { value: \"hr\", label: \"HR & People\" },\n { value: \"marketing\", label: \"Marketing\" },\n { value: \"project-management\", label: \"Project Management\" },\n { value: \"security\", label: \"Security\" },\n { value: \"support\", label: \"Support\" },\n { value: \"other\", label: \"Other\" },\n];\n\nfunction generateSlug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Mark that the user has interacted with setup so the dashboard gate won't redirect again. */\nfunction markSetupSeen() {\n try {\n localStorage.setItem(\"devportal_setup_dismissed\", \"1\");\n } catch {\n // localStorage unavailable — not critical\n }\n}\n\n// ─── Step indicator ────────────────────────────────────────────────────────\n\nconst STEPS: { key: SetupStep; label: string }[] = [\n { key: \"org\", label: \"Organization\" },\n { key: \"app\", label: \"First app\" },\n { key: \"done\", label: \"Done\" },\n];\n\nconst StepIndicator: FC<{ current: SetupStep }> = ({ current }) => {\n const currentIdx = STEPS.findIndex((s) => s.key === current);\n return (\n <div className=\"flex items-center gap-0\">\n {STEPS.map((step, idx) => {\n const isCompleted = idx < currentIdx;\n const isActive = idx === currentIdx;\n return (\n <div key={step.key} className=\"flex items-center\">\n <div className=\"flex flex-col items-center gap-1.5\">\n <div\n className={[\n \"flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold transition-colors\",\n isCompleted\n ? \"bg-action-primary-bg text-action-primary-text\"\n : isActive\n ? \"bg-action-primary-bg text-action-primary-text ring-4 ring-primary/20\"\n : \"bg-bg-sunken text-text-secondary\",\n ].join(\" \")}\n >\n {isCompleted ? <Check size={14} /> : idx + 1}\n </div>\n <span\n className={[\n \"text-xs font-medium whitespace-nowrap\",\n isActive ? \"text-text-primary\" : \"text-text-secondary\",\n ].join(\" \")}\n >\n {step.label}\n </span>\n </div>\n {idx < STEPS.length - 1 && (\n <div\n className={[\n \"mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors\",\n idx < currentIdx ? \"bg-action-primary-bg\" : \"bg-border\",\n ].join(\" \")}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n};\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport const SetupPage: FC = () => {\n const { navigate, basePath, currentUser } = useDevportal();\n const { t } = useI18n();\n const bus = useDevportalEventBus();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const handleNavigate = (path: string) => navigate?.(`${basePath}${path}`);\n\n const [step, setStep] = useState<SetupStep>(\"org\");\n\n // IDs created during wizard — carried forward for success CTAs\n const [createdOrgId, setCreatedOrgId] = useState<string | null>(null);\n const [createdAppId, setCreatedAppId] = useState<string | null>(null);\n\n // ── Step 1: org ──────────────────────────────────────────────\n const [orgName, setOrgName] = useState(\"\");\n const [orgSlug, setOrgSlug] = useState(\"\");\n const [orgDescription, setOrgDescription] = useState(\"\");\n const [orgErrors, setOrgErrors] = useState<{ name?: string; slug?: string }>(\n {},\n );\n\n const [createOrg, { loading: creatingOrg }] = useCreateOrganizationMutation();\n const [createBillingAccountMutation] = useCreateBillingAccountMutation();\n\n const validateOrg = () => {\n const errs: { name?: string; slug?: string } = {};\n if (!orgName.trim())\n errs.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n else if (orgName.length < 2)\n errs.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n if (!orgSlug.trim())\n errs.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n else if (!/^[a-z0-9-]+$/.test(orgSlug))\n errs.slug = tr(\n \"devportal.slugInvalid\",\n \"Lowercase letters, numbers, and hyphens only\",\n );\n setOrgErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleOrgSubmit = async () => {\n if (!validateOrg()) return;\n try {\n const result = await createOrg({\n variables: {\n input: {\n name: orgName,\n slug: orgSlug || undefined,\n description: orgDescription || undefined,\n },\n },\n });\n const id = result.data?.createDeveloperOrganization?.id;\n if (id) {\n bus.emit(\"devportal.org.created\", {\n organizationId: id,\n name: orgName,\n });\n setCreatedOrgId(id);\n // Fire-and-forget: create a billing account for the new org\n try {\n createBillingAccountMutation({\n variables: {\n input: {\n name: orgName,\n email: currentUser?.email ?? \"\",\n },\n },\n }).catch(() => {});\n } catch {\n // silent failure — billing account creation is non-blocking\n }\n setStep(\"app\");\n }\n } catch {\n // error surfaced via Apollo cache; leave the form open\n }\n };\n\n // ── Step 2: app ──────────────────────────────────────────────\n const [appName, setAppName] = useState(\"\");\n const [appSlug, setAppSlug] = useState(\"\");\n const [appType, setAppType] = useState<AppType | \"\">(\"\");\n const [appCategory, setAppCategory] = useState(\"\");\n const [appShortDesc, setAppShortDesc] = useState(\"\");\n const [appErrors, setAppErrors] = useState<{\n name?: string;\n appType?: string;\n category?: string;\n shortDescription?: string;\n }>({});\n\n const [createApp, { loading: creatingApp }] = useCreateApplicationMutation();\n\n const validateApp = () => {\n const errs: typeof appErrors = {};\n if (!appName.trim())\n errs.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n else if (appName.length < 3)\n errs.name = tr(\n \"devportal.nameTooShort\",\n \"Name must be at least 3 characters\",\n );\n if (!appType)\n errs.appType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n if (!appCategory)\n errs.category = tr(\"devportal.categoryRequired\", \"Category is required\");\n if (!appShortDesc.trim())\n errs.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n setAppErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleAppSubmit = async () => {\n if (!validateApp()) return;\n try {\n const result = await createApp({\n variables: {\n input: {\n name: appName,\n slug: appSlug || undefined,\n appType: appType as AppType,\n category: appCategory || undefined,\n shortDescription: appShortDesc || undefined,\n visibility: \"PRIVATE\",\n developerOrganizationId: createdOrgId || undefined,\n },\n },\n });\n const id = result.data?.createApplication?.id;\n if (id) {\n bus.emit(\"devportal.app.created\", {\n appId: id,\n name: appName,\n appType,\n organizationId: createdOrgId,\n });\n setCreatedAppId(id);\n markSetupSeen();\n setStep(\"done\");\n }\n } catch {\n // error surfaced via Apollo cache\n }\n };\n\n const handleSkip = () => {\n markSetupSeen();\n handleNavigate(\"/\");\n };\n\n // ─── Render ─────────────────────────────────────────────────\n\n return (\n <main className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-2xl px-6 py-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Rocket size={20} />\n </div>\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\"devportal.developerPortal\", \"Developer Portal\")}\n </p>\n <h1 className=\"text-base font-semibold text-text-primary\">\n {tr(\"devportal.setup.title\", \"Get set up\")}\n </h1>\n </div>\n </div>\n {step !== \"done\" && (\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"mx-auto max-w-2xl px-6 py-10\">\n {/* Step indicator */}\n <div className=\"mb-10 flex justify-center\">\n <StepIndicator current={step} />\n </div>\n\n {/* Welcome / purpose — what this wizard sets up and why */}\n {step === \"org\" && (\n <div className=\"mb-8 flex flex-col items-center gap-3 text-center\">\n <Illustration\n name=\"onboarding\"\n alt={tr(\n \"devportal.setup.illustrationAlt\",\n \"Getting started with the developer portal\",\n )}\n size=\"md\"\n />\n <PagePurpose className=\"justify-center\">\n {tr(\n \"devportal.setup.purpose\",\n \"Two quick steps to start building: create the organization that owns your apps, then register your first app. You can change everything later — this just gets you to a working starting point.\",\n )}\n </PagePurpose>\n </div>\n )}\n\n {/* ── Step 1: Organization ─────────────────────── */}\n {step === \"org\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Building2 size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr(\"devportal.setup.orgTitle\", \"Set up your organization\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.setup.orgSubtitle\",\n \"This groups your apps and teams under one publisher identity.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={orgName}\n onChange={(e) => {\n setOrgName(e.target.value);\n if (!orgSlug || orgSlug === generateSlug(orgName)) {\n setOrgSlug(generateSlug(e.target.value));\n }\n setOrgErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={orgErrors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={orgSlug}\n onChange={(e) => {\n setOrgSlug(e.target.value.toLowerCase());\n setOrgErrors((p) => ({ ...p, slug: undefined }));\n }}\n placeholder=\"acme-dev\"\n required\n error={orgErrors.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={orgDescription}\n onChange={(e) => setOrgDescription(e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization…\",\n )}\n rows={2}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleOrgSubmit()}\n disabled={creatingOrg}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors\"\n >\n {creatingOrg ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createAndContinue\", \"Create & Continue\")}\n {!creatingOrg && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 2: First app ─────────────────────── */}\n {step === \"app\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <AppWindow size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr(\"devportal.setup.appTitle\", \"Create your first app\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.setup.appSubtitle\",\n \"Register the app you want to publish or integrate.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={appName}\n onChange={(e) => {\n setAppName(e.target.value);\n if (!appSlug || appSlug === generateSlug(appName)) {\n setAppSlug(generateSlug(e.target.value));\n }\n setAppErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={appErrors.name}\n />\n\n <div className=\"grid grid-cols-2 gap-4\">\n <SelectField\n label={tr(\"devportal.applicationType\", \"Application Type\")}\n value={appType}\n onChange={(e) => {\n setAppType(e.target.value as AppType);\n setAppErrors((p) => ({ ...p, appType: undefined }));\n }}\n options={APP_TYPE_OPTIONS}\n placeholder={tr(\"devportal.selectType\", \"Select type…\")}\n required\n error={appErrors.appType}\n />\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={appCategory}\n onChange={(e) => {\n setAppCategory(e.target.value);\n setAppErrors((p) => ({ ...p, category: undefined }));\n }}\n options={CATEGORY_OPTIONS}\n placeholder={tr(\n \"devportal.selectCategory\",\n \"Select category…\",\n )}\n required\n error={appErrors.category}\n />\n </div>\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={appShortDesc}\n onChange={(e) => {\n setAppShortDesc(e.target.value);\n setAppErrors((p) => ({ ...p, shortDescription: undefined }));\n }}\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={appErrors.shortDescription}\n rows={2}\n hint={`${appShortDesc.length}/200`}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAppSubmit()}\n disabled={creatingApp}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors\"\n >\n {creatingApp ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createApp\", \"Create App\")}\n {!creatingApp && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 3: Done ─────────────────────────── */}\n {step === \"done\" && (\n <div className=\"text-center\">\n <div className=\"mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-action-primary-bg/10 text-primary\">\n <Rocket size={32} />\n </div>\n <h2 className=\"text-2xl font-bold text-text-primary\">\n {tr(\"devportal.setup.doneTitle\", \"You're all set!\")}\n </h2>\n <p className=\"mt-2 text-text-secondary\">\n {tr(\n \"devportal.setup.doneSubtitle\",\n \"Your organization and first app are ready. Here's what to do next.\",\n )}\n </p>\n\n <div className=\"mt-8 grid gap-3 sm:grid-cols-2\">\n {createdAppId && (\n <NextStepCard\n icon={<AppWindow size={20} />}\n title={tr(\"devportal.setup.viewApp\", \"View your app\")}\n description={tr(\n \"devportal.setup.viewAppDesc\",\n \"Configure OAuth, webhooks, and versioning\",\n )}\n onClick={() => handleNavigate(`/apps/${createdAppId}`)}\n primary\n />\n )}\n <NextStepCard\n icon={<Key size={20} />}\n title={tr(\"devportal.setup.generateApiKey\", \"Generate API key\")}\n description={tr(\n \"devportal.setup.generateApiKeyDesc\",\n \"Create credentials to start calling APIs\",\n )}\n onClick={() => handleNavigate(\"/api-keys/new\")}\n />\n <NextStepCard\n icon={<BookOpen size={20} />}\n title={tr(\"devportal.setup.browseDocs\", \"Browse docs\")}\n description={tr(\n \"devportal.setup.browseDocsDesc\",\n \"Learn about publishing, SDKs, and webhooks\",\n )}\n onClick={() => handleNavigate(\"/docs\")}\n />\n {createdOrgId && (\n <NextStepCard\n icon={<Building2 size={20} />}\n title={tr(\"devportal.setup.inviteTeam\", \"Invite your team\")}\n description={tr(\n \"devportal.setup.inviteTeamDesc\",\n \"Add members to collaborate on your apps\",\n )}\n onClick={() =>\n handleNavigate(`/organizations/${createdOrgId}/members`)\n }\n />\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/\")}\n className=\"mt-8 inline-flex items-center gap-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.goToDashboard\", \"Go to dashboard\")}\n <ArrowRight size={14} />\n </button>\n </div>\n )}\n </div>\n </main>\n );\n};\n\n// ─── Next-step card ────────────────────────────────────────────────────────\n\nconst NextStepCard: FC<{\n icon: React.ReactNode;\n title: string;\n description: string;\n onClick: () => void;\n primary?: boolean;\n}> = ({ icon, title, description, onClick, primary }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={[\n \"flex items-start gap-4 rounded-xl border p-5 text-left transition-colors\",\n primary\n ? \"border-primary bg-action-primary-bg/5 hover:bg-action-primary-bg/10\"\n : \"border-border-default bg-surface-raised hover:bg-surface-hover\",\n ].join(\" \")}\n >\n <div\n className={[\n \"flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg\",\n primary\n ? \"bg-action-primary-bg/20 text-primary\"\n : \"bg-bg-sunken text-text-secondary\",\n ].join(\" \")}\n >\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-semibold text-text-primary\">{title}</p>\n <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-0.5 flex-shrink-0 text-text-secondary\"\n />\n </button>\n);\n"],"mappings":"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"}
1
+ {"version":3,"file":"SetupPage.js","names":[],"sources":["../../../src/devportal/pages/SetupPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n ArrowRight,\n Building2,\n AppWindow,\n Rocket,\n Check,\n Key,\n BookOpen,\n ChevronRight,\n Box,\n Puzzle,\n GitFork,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { Illustration, PagePurpose } from \"@burdenoff/fe-libs/ui\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useDevportalEventBus } from \"../events\";\nimport { cn } from \"../utils/cn\";\nimport {\n useCreateOrganizationMutation,\n useCreateApplicationMutation,\n} from \"../../generated/global-operations\";\nimport { useCreateBillingAccountMutation } from \"../hooks\";\n\ntype SetupStep = \"org\" | \"app\" | \"done\";\ntype BuilderType = \"app\" | \"node\" | \"workflow\";\n\nconst CATEGORY_OPTIONS = [\n { value: \"productivity\", label: \"Productivity\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"automation\", label: \"Automation\" },\n { value: \"developer-tools\", label: \"Developer Tools\" },\n { value: \"finance\", label: \"Finance\" },\n { value: \"hr\", label: \"HR & People\" },\n { value: \"marketing\", label: \"Marketing\" },\n { value: \"project-management\", label: \"Project Management\" },\n { value: \"security\", label: \"Security\" },\n { value: \"support\", label: \"Support\" },\n { value: \"other\", label: \"Other\" },\n];\n\nfunction generateSlug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Mark that the user has interacted with setup so the dashboard gate won't redirect again. */\nfunction markSetupSeen() {\n try {\n localStorage.setItem(\"devportal_setup_dismissed\", \"1\");\n } catch {\n // localStorage unavailable — not critical\n }\n}\n\n// ─── Step indicator ────────────────────────────────────────────────────────\n\nconst STEPS: { key: SetupStep; label: string }[] = [\n { key: \"org\", label: \"Organization\" },\n { key: \"app\", label: \"First app\" },\n { key: \"done\", label: \"Done\" },\n];\n\nconst StepIndicator: FC<{ current: SetupStep }> = ({ current }) => {\n const currentIdx = STEPS.findIndex((s) => s.key === current);\n return (\n <div className=\"flex items-center gap-0\">\n {STEPS.map((step, idx) => {\n const isCompleted = idx < currentIdx;\n const isActive = idx === currentIdx;\n return (\n <div key={step.key} className=\"flex items-center\">\n <div className=\"flex flex-col items-center gap-1.5\">\n <div\n className={[\n \"flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold transition-colors\",\n isCompleted\n ? \"bg-action-primary-bg text-action-primary-text\"\n : isActive\n ? \"bg-action-primary-bg text-action-primary-text ring-4 ring-primary/20\"\n : \"bg-bg-sunken text-text-secondary\",\n ].join(\" \")}\n >\n {isCompleted ? <Check size={14} /> : idx + 1}\n </div>\n <span\n className={[\n \"text-xs font-medium whitespace-nowrap\",\n isActive ? \"text-text-primary\" : \"text-text-secondary\",\n ].join(\" \")}\n >\n {step.label}\n </span>\n </div>\n {idx < STEPS.length - 1 && (\n <div\n className={[\n \"mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors\",\n idx < currentIdx ? \"bg-action-primary-bg\" : \"bg-border\",\n ].join(\" \")}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n};\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport const SetupPage: FC = () => {\n const { navigate, basePath, currentUser } = useDevportal();\n const { t } = useI18n();\n const bus = useDevportalEventBus();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const handleNavigate = (path: string) => navigate?.(`${basePath}${path}`);\n\n const [step, setStep] = useState<SetupStep>(\"org\");\n\n // IDs created during wizard — carried forward for success CTAs\n const [createdOrgId, setCreatedOrgId] = useState<string | null>(null);\n const [createdAppId, setCreatedAppId] = useState<string | null>(null);\n\n // ── Step 1: org ──────────────────────────────────────────────\n const [orgName, setOrgName] = useState(\"\");\n const [orgSlug, setOrgSlug] = useState(\"\");\n const [orgDescription, setOrgDescription] = useState(\"\");\n const [orgErrors, setOrgErrors] = useState<{ name?: string; slug?: string }>(\n {},\n );\n\n const [createOrg, { loading: creatingOrg }] = useCreateOrganizationMutation();\n const [createBillingAccountMutation] = useCreateBillingAccountMutation();\n\n const validateOrg = () => {\n const errs: { name?: string; slug?: string } = {};\n if (!orgName.trim())\n errs.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n else if (orgName.length < 2)\n errs.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n if (!orgSlug.trim())\n errs.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n else if (!/^[a-z0-9-]+$/.test(orgSlug))\n errs.slug = tr(\n \"devportal.slugInvalid\",\n \"Lowercase letters, numbers, and hyphens only\",\n );\n setOrgErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleOrgSubmit = async () => {\n if (!validateOrg()) return;\n try {\n const result = await createOrg({\n variables: {\n input: {\n name: orgName,\n slug: orgSlug || undefined,\n description: orgDescription || undefined,\n },\n },\n });\n const id = result.data?.createDeveloperOrganization?.id;\n if (id) {\n bus.emit(\"devportal.org.created\", {\n organizationId: id,\n name: orgName,\n });\n setCreatedOrgId(id);\n // Fire-and-forget: create a billing account for the new org\n try {\n createBillingAccountMutation({\n variables: {\n input: {\n name: orgName,\n email: currentUser?.email ?? \"\",\n },\n },\n }).catch(() => {});\n } catch {\n // silent failure — billing account creation is non-blocking\n }\n setStep(\"app\");\n }\n } catch {\n // error surfaced via Apollo cache; leave the form open\n }\n };\n\n // ── Step 2: app ──────────────────────────────────────────────\n const [appName, setAppName] = useState(\"\");\n const [appSlug, setAppSlug] = useState(\"\");\n const [builderType, setBuilderType] = useState<BuilderType | null>(null);\n const [appCategory, setAppCategory] = useState(\"\");\n const [appShortDesc, setAppShortDesc] = useState(\"\");\n const [appErrors, setAppErrors] = useState<{\n name?: string;\n builderType?: string;\n category?: string;\n shortDescription?: string;\n }>({});\n\n const [createApp, { loading: creatingApp }] = useCreateApplicationMutation();\n\n const appTypeForBuilder = () => {\n if (builderType === \"node\") return \"NODE\" as const;\n if (builderType === \"workflow\") return \"WORKFLOW\" as const;\n return \"API_INTEGRATION\" as const;\n };\n\n const validateApp = () => {\n const errs: typeof appErrors = {};\n if (!appName.trim())\n errs.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n else if (appName.length < 3)\n errs.name = tr(\n \"devportal.nameTooShort\",\n \"Name must be at least 3 characters\",\n );\n if (!builderType)\n errs.builderType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n if (!appCategory)\n errs.category = tr(\"devportal.categoryRequired\", \"Category is required\");\n if (!appShortDesc.trim())\n errs.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n setAppErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleAppSubmit = async () => {\n if (!validateApp()) return;\n const resolvedType = appTypeForBuilder();\n try {\n const result = await createApp({\n variables: {\n input: {\n name: appName,\n slug: appSlug || undefined,\n appType: resolvedType,\n category: appCategory || undefined,\n shortDescription: appShortDesc || undefined,\n visibility: \"PRIVATE\",\n developerOrganizationId: createdOrgId || undefined,\n },\n },\n });\n const id = result.data?.createApplication?.id;\n if (id) {\n bus.emit(\"devportal.app.created\", {\n appId: id,\n name: appName,\n appType: resolvedType,\n organizationId: createdOrgId,\n });\n setCreatedAppId(id);\n markSetupSeen();\n setStep(\"done\");\n }\n } catch {\n // error surfaced via Apollo cache\n }\n };\n\n const handleSkip = () => {\n markSetupSeen();\n handleNavigate(\"/\");\n };\n\n // ─── Render ─────────────────────────────────────────────────\n\n return (\n <main className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-2xl px-6 py-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Rocket size={20} />\n </div>\n <div>\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\"devportal.developerPortal\", \"Developer Portal\")}\n </p>\n <h1 className=\"text-base font-semibold text-text-primary\">\n {tr(\"devportal.setup.title\", \"Get set up\")}\n </h1>\n </div>\n </div>\n {step !== \"done\" && (\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"mx-auto max-w-2xl px-6 py-10\">\n {/* Step indicator */}\n <div className=\"mb-10 flex justify-center\">\n <StepIndicator current={step} />\n </div>\n\n {/* Welcome / purpose — what this wizard sets up and why */}\n {step === \"org\" && (\n <div className=\"mb-8 flex flex-col items-center gap-3 text-center\">\n <Illustration\n name=\"onboarding\"\n alt={tr(\n \"devportal.setup.illustrationAlt\",\n \"Getting started with the developer portal\",\n )}\n size=\"md\"\n />\n <PagePurpose className=\"justify-center\">\n {tr(\n \"devportal.setup.purpose\",\n \"Two quick steps to start building: create the organization that owns your apps, then register your first app. You can change everything later — this just gets you to a working starting point.\",\n )}\n </PagePurpose>\n </div>\n )}\n\n {/* ── Step 1: Organization ─────────────────────── */}\n {step === \"org\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <Building2 size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr(\"devportal.setup.orgTitle\", \"Set up your organization\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.setup.orgSubtitle\",\n \"This groups your apps and teams under one publisher identity.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={orgName}\n onChange={(e) => {\n setOrgName(e.target.value);\n if (!orgSlug || orgSlug === generateSlug(orgName)) {\n setOrgSlug(generateSlug(e.target.value));\n }\n setOrgErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={orgErrors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={orgSlug}\n onChange={(e) => {\n setOrgSlug(e.target.value.toLowerCase());\n setOrgErrors((p) => ({ ...p, slug: undefined }));\n }}\n placeholder=\"acme-dev\"\n required\n error={orgErrors.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={orgDescription}\n onChange={(e) => setOrgDescription(e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization…\",\n )}\n rows={2}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleOrgSubmit()}\n disabled={creatingOrg}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors\"\n >\n {creatingOrg ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createAndContinue\", \"Create & Continue\")}\n {!creatingOrg && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 2: First app ─────────────────────── */}\n {step === \"app\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-action-primary-bg/10 text-primary\">\n <AppWindow size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tr(\"devportal.setup.appTitle\", \"Create your first app\")}\n </h2>\n <p className=\"text-sm text-text-secondary\">\n {tr(\n \"devportal.setup.appSubtitle\",\n \"Register the app you want to publish or integrate.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={appName}\n onChange={(e) => {\n setAppName(e.target.value);\n if (!appSlug || appSlug === generateSlug(appName)) {\n setAppSlug(generateSlug(e.target.value));\n }\n setAppErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={appErrors.name}\n />\n\n {/* Builder type picker */}\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">\n {tr(\"devportal.applicationType\", \"Application Type\")}{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </p>\n <div className=\"grid grid-cols-3 gap-3\">\n <SetupTypeCard\n icon={Box}\n title=\"App\"\n description=\"OAuth integration for the platform\"\n selected={builderType === \"app\"}\n onClick={() => {\n setBuilderType(\"app\");\n setAppErrors((p) => ({ ...p, builderType: undefined }));\n }}\n />\n <SetupTypeCard\n icon={Puzzle}\n title=\"Node\"\n description=\"Custom FluidGrids workflow node\"\n selected={builderType === \"node\"}\n onClick={() => {\n setBuilderType(\"node\");\n setAppErrors((p) => ({ ...p, builderType: undefined }));\n }}\n />\n <SetupTypeCard\n icon={GitFork}\n title=\"Workflow\"\n description=\"Reusable automation template\"\n selected={builderType === \"workflow\"}\n onClick={() => {\n setBuilderType(\"workflow\");\n setAppErrors((p) => ({ ...p, builderType: undefined }));\n }}\n />\n </div>\n {appErrors.builderType && (\n <p className=\"mt-1.5 text-xs text-status-error-text\">\n {appErrors.builderType}\n </p>\n )}\n </div>\n\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={appCategory}\n onChange={(e) => {\n setAppCategory(e.target.value);\n setAppErrors((p) => ({ ...p, category: undefined }));\n }}\n options={CATEGORY_OPTIONS}\n placeholder={tr(\"devportal.selectCategory\", \"Select category…\")}\n required\n error={appErrors.category}\n />\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={appShortDesc}\n onChange={(e) => {\n setAppShortDesc(e.target.value);\n setAppErrors((p) => ({ ...p, shortDescription: undefined }));\n }}\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={appErrors.shortDescription}\n rows={2}\n hint={`${appShortDesc.length}/200`}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAppSubmit()}\n disabled={creatingApp}\n className=\"inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-semibold text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-60 transition-colors\"\n >\n {creatingApp ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createApp\", \"Create App\")}\n {!creatingApp && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 3: Done ─────────────────────────── */}\n {step === \"done\" && (\n <div className=\"text-center\">\n <div className=\"mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-action-primary-bg/10 text-primary\">\n <Rocket size={32} />\n </div>\n <h2 className=\"text-2xl font-bold text-text-primary\">\n {tr(\"devportal.setup.doneTitle\", \"You're all set!\")}\n </h2>\n <p className=\"mt-2 text-text-secondary\">\n {tr(\n \"devportal.setup.doneSubtitle\",\n \"Your organization and first app are ready. Here's what to do next.\",\n )}\n </p>\n\n <div className=\"mt-8 grid gap-3 sm:grid-cols-2\">\n {createdAppId && (\n <NextStepCard\n icon={<AppWindow size={20} />}\n title={tr(\"devportal.setup.viewApp\", \"View your app\")}\n description={tr(\n \"devportal.setup.viewAppDesc\",\n \"Configure OAuth, webhooks, and versioning\",\n )}\n onClick={() => handleNavigate(`/apps/${createdAppId}`)}\n primary\n />\n )}\n <NextStepCard\n icon={<Key size={20} />}\n title={tr(\"devportal.setup.generateApiKey\", \"Generate API key\")}\n description={tr(\n \"devportal.setup.generateApiKeyDesc\",\n \"Create credentials to start calling APIs\",\n )}\n onClick={() => handleNavigate(\"/api-keys/new\")}\n />\n <NextStepCard\n icon={<BookOpen size={20} />}\n title={tr(\"devportal.setup.browseDocs\", \"Browse docs\")}\n description={tr(\n \"devportal.setup.browseDocsDesc\",\n \"Learn about publishing, SDKs, and webhooks\",\n )}\n onClick={() => handleNavigate(\"/docs\")}\n />\n {createdOrgId && (\n <NextStepCard\n icon={<Building2 size={20} />}\n title={tr(\"devportal.setup.inviteTeam\", \"Invite your team\")}\n description={tr(\n \"devportal.setup.inviteTeamDesc\",\n \"Add members to collaborate on your apps\",\n )}\n onClick={() =>\n handleNavigate(`/organizations/${createdOrgId}/members`)\n }\n />\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/\")}\n className=\"mt-8 inline-flex items-center gap-2 text-sm text-text-secondary hover:text-text-primary transition-colors\"\n >\n {tr(\"devportal.setup.goToDashboard\", \"Go to dashboard\")}\n <ArrowRight size={14} />\n </button>\n </div>\n )}\n </div>\n </main>\n );\n};\n\n// ─── Setup type card ───────────────────────────────────────────────────────\n\nconst SetupTypeCard: FC<{\n icon: FC<{ size?: number; className?: string }>;\n title: string;\n description: string;\n selected: boolean;\n onClick: () => void;\n}> = ({ icon: Icon, title, description, selected, onClick }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"relative flex flex-col gap-2 rounded-xl border-2 p-4 text-left transition-all hover:border-primary/50 hover:shadow-sm\",\n selected\n ? \"border-primary bg-action-primary-bg/5 shadow-sm\"\n : \"border-border-subtle bg-bg-surface\",\n )}\n >\n {selected && (\n <span className=\"absolute top-3 right-3 flex h-4 w-4 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text\">\n <Check size={10} />\n </span>\n )}\n <div className=\"flex h-8 w-8 items-center justify-center rounded-lg bg-bg-sunken\">\n <Icon size={18} className=\"text-text-primary\" />\n </div>\n <div>\n <p className=\"text-sm font-semibold text-text-primary\">{title}</p>\n <p className=\"mt-0.5 text-xs text-text-secondary\">{description}</p>\n </div>\n </button>\n);\n\n// ─── Next-step card ────────────────────────────────────────────────────────\n\nconst NextStepCard: FC<{\n icon: React.ReactNode;\n title: string;\n description: string;\n onClick: () => void;\n primary?: boolean;\n}> = ({ icon, title, description, onClick, primary }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={[\n \"flex items-start gap-4 rounded-xl border p-5 text-left transition-colors\",\n primary\n ? \"border-primary bg-action-primary-bg/5 hover:bg-action-primary-bg/10\"\n : \"border-border-default bg-surface-raised hover:bg-surface-hover\",\n ].join(\" \")}\n >\n <div\n className={[\n \"flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg\",\n primary\n ? \"bg-action-primary-bg/20 text-primary\"\n : \"bg-bg-sunken text-text-secondary\",\n ].join(\" \")}\n >\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-semibold text-text-primary\">{title}</p>\n <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-0.5 flex-shrink-0 text-text-secondary\"\n />\n </button>\n);\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-devportal",
3
- "version": "2026.713.9",
3
+ "version": "2026.714.2",
4
4
  "description": "Burdenoff Developer Portal Microfrontend - Complete developer operations interface",
5
5
  "type": "module",
6
6
  "files": [