@burdenoff/microfe-devportal 2026.914.1 → 2026.914.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devportal/DevportalRoutes.d.ts.map +1 -1
- package/dist/devportal/DevportalRoutes.js +130 -110
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/components/SectionNav.d.ts +10 -1
- package/dist/devportal/components/SectionNav.d.ts.map +1 -1
- package/dist/devportal/components/SectionNav.js +60 -42
- package/dist/devportal/components/SectionNav.js.map +1 -1
- package/dist/devportal/hooks/useIsSellerSection.d.ts +13 -0
- package/dist/devportal/hooks/useIsSellerSection.d.ts.map +1 -0
- package/dist/devportal/hooks/useIsSellerSection.js +15 -0
- package/dist/devportal/hooks/useIsSellerSection.js.map +1 -0
- package/dist/devportal/pages/CreateOrganizationPage.d.ts.map +1 -1
- package/dist/devportal/pages/CreateOrganizationPage.js +107 -106
- package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.js +349 -336
- package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +291 -290
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.d.ts.map +1 -1
- package/dist/devportal/pages/OrganizationsPage.js +102 -101
- package/dist/devportal/pages/OrganizationsPage.js.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js +210 -209
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.d.ts.map +1 -1
- package/dist/devportal/pages/SellerDashboardPage.js +14 -22
- package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
- package/dist/generated/global-operations.d.ts +102 -12
- package/dist/generated/global-operations.d.ts.map +1 -1
- package/dist/generated/global-operations.js +107 -92
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +2963 -242
- package/dist/generated/global-types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1,70 +1,88 @@
|
|
|
1
1
|
import { useDevportal as e } from "../providers/DevportalProvider.js";
|
|
2
2
|
import { useTr as t } from "../utils/i18n.js";
|
|
3
3
|
import { cn as n } from "../utils/cn.js";
|
|
4
|
-
import {
|
|
4
|
+
import { orgSectionPath as r, useIsSellerSection as i } from "../hooks/useIsSellerSection.js";
|
|
5
|
+
import { useGetMyOrganizationsQuery as a } from "../../generated/global-operations.js";
|
|
5
6
|
import "../hooks/useGraphQL.js";
|
|
6
|
-
import { useEffect as
|
|
7
|
-
import { Building2 as
|
|
7
|
+
import { useEffect as o, useRef as s, useState as c } from "react";
|
|
8
|
+
import { Building2 as l, Check as u, ChevronDown as d, Plus as f } from "lucide-react";
|
|
8
9
|
import "react-router";
|
|
9
|
-
import { jsx as
|
|
10
|
+
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
10
11
|
//#region src/devportal/components/SectionNav.tsx
|
|
11
|
-
var
|
|
12
|
-
let { activeOrgId:
|
|
13
|
-
|
|
14
|
-
!
|
|
12
|
+
var h = () => {
|
|
13
|
+
let { activeOrgId: h, setActiveOrgId: g, activePhysicalOrgId: _, setActivePhysicalOrgId: v, navigate: y, basePath: b } = e(), x = i(), S = x ? _ : h, C = x ? v : g, w = t(), [T, E] = c(!1), D = s(null), { data: O } = a({ fetchPolicy: "cache-first" }), k = (O?.myDeveloperOrganizations ?? []).filter((e) => x ? e.kind === "PHYSICAL" : e.kind !== "PHYSICAL");
|
|
14
|
+
o(() => {
|
|
15
|
+
!S && k.length === 1 && k[0]?.id && C(k[0].id);
|
|
15
16
|
}, [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
]),
|
|
17
|
+
k,
|
|
18
|
+
S,
|
|
19
|
+
C
|
|
20
|
+
]), o(() => {
|
|
20
21
|
let e = (e) => {
|
|
21
|
-
|
|
22
|
+
D.current && !D.current.contains(e.target) && E(!1);
|
|
22
23
|
};
|
|
23
|
-
return
|
|
24
|
-
}, [
|
|
25
|
-
let
|
|
26
|
-
return /* @__PURE__ */
|
|
27
|
-
ref:
|
|
24
|
+
return T && document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
25
|
+
}, [T]);
|
|
26
|
+
let A = k.find((e) => e.id === S)?.name ?? (k.length === 0 ? w("devportal.nav.noOrg", "No organization") : w("devportal.nav.selectOrg", "Select org")), j = r(x, "new");
|
|
27
|
+
return /* @__PURE__ */ m("div", {
|
|
28
|
+
ref: D,
|
|
28
29
|
className: "relative flex-shrink-0",
|
|
29
|
-
children: [/* @__PURE__ */
|
|
30
|
+
children: [/* @__PURE__ */ m("button", {
|
|
30
31
|
type: "button",
|
|
31
|
-
onClick: () =>
|
|
32
|
+
onClick: () => E((e) => !e),
|
|
32
33
|
className: n("inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors", "bg-bg-surface text-text-primary border-border-subtle hover:bg-accent"),
|
|
33
|
-
"aria-label":
|
|
34
|
+
"aria-label": w("devportal.nav.switchOrg", "Switch organization"),
|
|
34
35
|
children: [
|
|
35
|
-
/* @__PURE__ */
|
|
36
|
+
/* @__PURE__ */ p(l, {
|
|
36
37
|
size: 13,
|
|
37
38
|
className: "text-primary flex-shrink-0"
|
|
38
39
|
}),
|
|
39
|
-
/* @__PURE__ */
|
|
40
|
+
/* @__PURE__ */ p("span", {
|
|
40
41
|
className: "max-w-[140px] truncate",
|
|
41
|
-
children:
|
|
42
|
+
children: A
|
|
42
43
|
}),
|
|
43
|
-
/* @__PURE__ */
|
|
44
|
+
/* @__PURE__ */ p(d, {
|
|
44
45
|
size: 13,
|
|
45
|
-
className: n("transition-transform",
|
|
46
|
+
className: n("transition-transform", T && "rotate-180")
|
|
46
47
|
})
|
|
47
48
|
]
|
|
48
|
-
}),
|
|
49
|
+
}), T && /* @__PURE__ */ m("div", {
|
|
49
50
|
className: "absolute right-0 top-full z-50 mt-1 min-w-[200px] rounded-md border border-border-subtle bg-popover shadow-lg py-1",
|
|
50
|
-
children:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
51
|
+
children: [
|
|
52
|
+
k.map((e) => /* @__PURE__ */ m("button", {
|
|
53
|
+
type: "button",
|
|
54
|
+
onClick: () => {
|
|
55
|
+
C(e.id), E(!1);
|
|
56
|
+
},
|
|
57
|
+
className: n("flex w-full items-center gap-2 px-3 py-2 text-sm text-left transition-colors hover:bg-accent", e.id === S ? "text-primary font-medium" : "text-text-primary"),
|
|
58
|
+
children: [/* @__PURE__ */ p(u, {
|
|
59
|
+
size: 13,
|
|
60
|
+
className: n("flex-shrink-0", e.id === S ? "opacity-100 text-primary" : "opacity-0")
|
|
61
|
+
}), /* @__PURE__ */ p("span", {
|
|
62
|
+
className: "truncate",
|
|
63
|
+
children: e.name
|
|
64
|
+
})]
|
|
65
|
+
}, e.id)),
|
|
66
|
+
k.length > 0 && /* @__PURE__ */ p("div", { className: "my-1 border-t border-border-subtle" }),
|
|
67
|
+
/* @__PURE__ */ m("button", {
|
|
68
|
+
type: "button",
|
|
69
|
+
onClick: () => {
|
|
70
|
+
E(!1), y?.(`${b ?? ""}${j}`);
|
|
71
|
+
},
|
|
72
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-sm text-left text-primary transition-colors hover:bg-accent",
|
|
73
|
+
children: [/* @__PURE__ */ p(f, {
|
|
74
|
+
size: 13,
|
|
75
|
+
className: "flex-shrink-0"
|
|
76
|
+
}), /* @__PURE__ */ p("span", {
|
|
77
|
+
className: "truncate",
|
|
78
|
+
children: w("devportal.nav.newOrganization", "New organization")
|
|
79
|
+
})]
|
|
80
|
+
})
|
|
81
|
+
]
|
|
64
82
|
})]
|
|
65
83
|
});
|
|
66
84
|
};
|
|
67
85
|
//#endregion
|
|
68
|
-
export {
|
|
86
|
+
export { h as OrgSwitcher };
|
|
69
87
|
|
|
70
88
|
//# sourceMappingURL=SectionNav.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionNav.js","names":[],"sources":["../../../src/devportal/components/SectionNav.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useLocation } from \"react-router\";\nimport {\n LayoutDashboard,\n AppWindow,\n Building2,\n Share2,\n DollarSign,\n BookOpen,\n Library,\n User,\n Settings,\n ChevronDown,\n Check,\n} from \"lucide-react\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n useGetMyOrganizationsQuery,\n type GetMyOrganizationsQuery,\n} from \"../hooks/useGraphQL\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype OrgItem = GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number];\n\ninterface SectionDef {\n path: string;\n i18nKey: string;\n fallback: string;\n icon: typeof LayoutDashboard;\n /** Additional sub-paths that should mark this section as active. */\n matchPrefixes?: string[];\n}\n\nconst SECTIONS: ReadonlyArray<SectionDef> = [\n {\n path: \"\",\n i18nKey: \"devportal.nav.dashboard\",\n fallback: \"Dashboard\",\n icon: LayoutDashboard,\n },\n {\n path: \"apps\",\n i18nKey: \"devportal.nav.apps\",\n fallback: \"Apps\",\n icon: AppWindow,\n },\n {\n path: \"organizations\",\n i18nKey: \"devportal.nav.organizations\",\n fallback: \"Organizations\",\n icon: Building2,\n },\n {\n path: \"delegations\",\n i18nKey: \"devportal.nav.delegations\",\n fallback: \"Delegations\",\n icon: Share2,\n },\n {\n path: \"revenue\",\n i18nKey: \"devportal.nav.revenue\",\n fallback: \"Revenue\",\n icon: DollarSign,\n },\n {\n path: \"docs\",\n i18nKey: \"devportal.nav.docs\",\n fallback: \"Docs\",\n icon: BookOpen,\n },\n {\n path: \"resources\",\n i18nKey: \"devportal.nav.resources\",\n fallback: \"Resources\",\n icon: Library,\n },\n {\n path: \"publisher/profile\",\n i18nKey: \"devportal.nav.publisher\",\n fallback: \"Publisher\",\n icon: User,\n matchPrefixes: [\"publisher\"],\n },\n {\n path: \"settings\",\n i18nKey: \"devportal.nav.settings\",\n fallback: \"Settings\",\n icon: Settings,\n },\n];\n\nfunction joinBaseAndPath(basePath: string | undefined, path: string): string {\n const base = (basePath ?? \"\").replace(/\\/$/, \"\");\n if (!path) return base || \"/\";\n const suffix = path.startsWith(\"/\") ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\nfunction isSectionActive(\n pathname: string,\n basePath: string | undefined,\n section: SectionDef,\n): boolean {\n const sectionUrl = joinBaseAndPath(basePath, section.path);\n // Index/dashboard is active only when exactly matched (or with empty extra).\n if (section.path === \"\") {\n return pathname === sectionUrl || pathname === `${sectionUrl}/`;\n }\n const candidates = [section.path, ...(section.matchPrefixes ?? [])];\n return candidates.some((prefix) => {\n const url = joinBaseAndPath(basePath, prefix);\n return pathname === url || pathname.startsWith(`${url}/`);\n });\n}\n\n/** Org context switcher — can be embedded standalone or inside SectionNav. */\nexport const OrgSwitcher: FC = () => {\n const { activeOrgId, setActiveOrgId } = useDevportal();\n const tr = useTr();\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n const { data } = useGetMyOrganizationsQuery({ fetchPolicy: \"cache-first\" });\n const orgs: OrgItem[] = data?.myDeveloperOrganizations ?? [];\n\n // Auto-select when there's exactly one org and nothing is stored yet\n useEffect(() => {\n if (!activeOrgId && orgs.length === 1 && orgs[0]?.id) {\n setActiveOrgId(orgs[0].id);\n }\n }, [orgs, activeOrgId, setActiveOrgId]);\n\n // Close on outside click\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n if (open) document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n if (orgs.length === 0) return null;\n\n const activeOrg = orgs.find((o) => o.id === activeOrgId);\n const label = activeOrg?.name ?? tr(\"devportal.nav.selectOrg\", \"Select org\");\n\n return (\n <div ref={ref} className=\"relative flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors\",\n \"bg-bg-surface text-text-primary border-border-subtle hover:bg-accent\",\n )}\n aria-label={tr(\"devportal.nav.switchOrg\", \"Switch organization\")}\n >\n <Building2 size={13} className=\"text-primary flex-shrink-0\" />\n <span className=\"max-w-[140px] truncate\">{label}</span>\n <ChevronDown\n size={13}\n className={cn(\"transition-transform\", open && \"rotate-180\")}\n />\n </button>\n\n {open && (\n <div className=\"absolute right-0 top-full z-50 mt-1 min-w-[200px] rounded-md border border-border-subtle bg-popover shadow-lg py-1\">\n {orgs.map((org) => (\n <button\n key={org.id}\n type=\"button\"\n onClick={() => {\n setActiveOrgId(org.id);\n setOpen(false);\n }}\n className={cn(\n \"flex w-full items-center gap-2 px-3 py-2 text-sm text-left transition-colors hover:bg-accent\",\n org.id === activeOrgId\n ? \"text-primary font-medium\"\n : \"text-text-primary\",\n )}\n >\n <Check\n size={13}\n className={cn(\n \"flex-shrink-0\",\n org.id === activeOrgId\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <span className=\"truncate\">{org.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Horizontal section nav rendered above the page content on every devportal\n * route. Gives developers a one-click jump between all top-level sections so\n * routes like OAuth, Delegations, Analytics, Revenue, Docs, Resources,\n * Publisher Profile, and Settings are reachable without typing URLs.\n *\n * Renders nothing when `basePath` is undefined (standalone/dev mode) so it\n * doesn't conflict with whatever harness wraps the MFE there.\n */\nexport const SectionNav: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { pathname } = useLocation();\n const tr = useTr();\n\n if (!basePath || !navigate) return null;\n\n const handleClick = (path: string) => {\n navigate(joinBaseAndPath(basePath, path));\n };\n\n return (\n <nav\n aria-label={tr(\"devportal.nav.sections\", \"Developer portal sections\")}\n className=\"border-b border-border-subtle bg-bg-surface/40 px-4 py-2\"\n data-testid=\"devportal-section-nav\"\n >\n <div className=\"flex items-center gap-2\">\n <ul className=\"flex flex-1 flex-wrap gap-1\">\n {SECTIONS.map((section) => {\n const active = isSectionActive(pathname, basePath, section);\n const Icon = section.icon;\n return (\n <li key={section.path}>\n <button\n type=\"button\"\n onClick={() => handleClick(section.path)}\n aria-current={active ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n active\n ? \"bg-action-primary-bg text-action-primary-text\"\n : \"text-text-secondary hover:bg-accent hover:text-text-primary\",\n )}\n >\n <Icon size={14} />\n <span>{tr(section.i18nKey, section.fallback)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n <OrgSwitcher />\n </div>\n </nav>\n );\n};\n\n// Exported for unit tests that want to assert against the canonical list.\nexport const __SECTION_NAV_SECTIONS = SECTIONS;\n"],"mappings":";;;;;;;;;;AAsHA,IAAa,UAAwB;CACnC,IAAM,EAAE,gBAAa,sBAAmB,GAAc,EAChD,IAAK,GAAO,EACZ,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAM,EAAuB,KAAK,EAElC,EAAE,YAAS,EAA2B,EAAE,aAAa,eAAe,CAAC,EACrE,IAAkB,GAAM,4BAA4B,EAAE;AAoB5D,KAjBA,QAAgB;AACd,EAAI,CAAC,KAAe,EAAK,WAAW,KAAK,EAAK,IAAI,MAChD,EAAe,EAAK,GAAG,GAAG;IAE3B;EAAC;EAAM;EAAa;EAAe,CAAC,EAGvC,QAAgB;EACd,IAAM,KAAW,MAAkB;AACjC,GAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,OAAe,IACxD,EAAQ,GAAM;;AAIlB,SADI,KAAM,SAAS,iBAAiB,aAAa,EAAQ,QAC5C,SAAS,oBAAoB,aAAa,EAAQ;IAC9D,CAAC,EAAK,CAAC,EAEN,EAAK,WAAW,EAAG,QAAO;CAG9B,IAAM,IADY,EAAK,MAAM,MAAM,EAAE,OAAO,EAAY,EAC/B,QAAQ,EAAG,2BAA2B,aAAa;AAE5E,QACE,kBAAC,OAAD;EAAU;EAAK,WAAU;YAAzB,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,GAAS,MAAM,CAAC,EAAE;GACjC,WAAW,EACT,wGACA,uEACD;GACD,cAAY,EAAG,2BAA2B,sBAAsB;aAPlE;IASE,kBAAC,GAAD;KAAW,MAAM;KAAI,WAAU;KAA+B,CAAA;IAC9D,kBAAC,QAAD;KAAM,WAAU;eAA0B;KAAa,CAAA;IACvD,kBAAC,GAAD;KACE,MAAM;KACN,WAAW,EAAG,wBAAwB,KAAQ,aAAa;KAC3D,CAAA;IACK;MAER,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ,EAAK,KAAK,MACT,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe;AAEb,KADA,EAAe,EAAI,GAAG,EACtB,EAAQ,GAAM;;IAEhB,WAAW,EACT,gGACA,EAAI,OAAO,IACP,6BACA,oBACL;cAZH,CAcE,kBAAC,GAAD;KACE,MAAM;KACN,WAAW,EACT,iBACA,EAAI,OAAO,IACP,6BACA,YACL;KACD,CAAA,EACF,kBAAC,QAAD;KAAM,WAAU;eAAY,EAAI;KAAY,CAAA,CACrC;MAvBF,EAAI,GAuBF,CACT;GACE,CAAA,CAEJ"}
|
|
1
|
+
{"version":3,"file":"SectionNav.js","names":[],"sources":["../../../src/devportal/components/SectionNav.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport { useLocation } from \"react-router\";\nimport {\n LayoutDashboard,\n AppWindow,\n Building2,\n Share2,\n DollarSign,\n BookOpen,\n Library,\n User,\n Settings,\n ChevronDown,\n Check,\n Plus,\n} from \"lucide-react\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport {\n useIsSellerSection,\n orgSectionPath,\n} from \"../hooks/useIsSellerSection\";\nimport {\n useGetMyOrganizationsQuery,\n type GetMyOrganizationsQuery,\n} from \"../hooks/useGraphQL\";\nimport { cn } from \"../utils/cn\";\nimport { useTr } from \"../utils/i18n\";\n\ntype OrgItem = GetMyOrganizationsQuery[\"myDeveloperOrganizations\"][number];\n\ninterface SectionDef {\n path: string;\n i18nKey: string;\n fallback: string;\n icon: typeof LayoutDashboard;\n /** Additional sub-paths that should mark this section as active. */\n matchPrefixes?: string[];\n}\n\nconst SECTIONS: ReadonlyArray<SectionDef> = [\n {\n path: \"\",\n i18nKey: \"devportal.nav.dashboard\",\n fallback: \"Dashboard\",\n icon: LayoutDashboard,\n },\n {\n path: \"apps\",\n i18nKey: \"devportal.nav.apps\",\n fallback: \"Apps\",\n icon: AppWindow,\n },\n {\n path: \"organizations\",\n i18nKey: \"devportal.nav.organizations\",\n fallback: \"Organizations\",\n icon: Building2,\n },\n {\n path: \"delegations\",\n i18nKey: \"devportal.nav.delegations\",\n fallback: \"Delegations\",\n icon: Share2,\n },\n {\n path: \"revenue\",\n i18nKey: \"devportal.nav.revenue\",\n fallback: \"Revenue\",\n icon: DollarSign,\n },\n {\n path: \"docs\",\n i18nKey: \"devportal.nav.docs\",\n fallback: \"Docs\",\n icon: BookOpen,\n },\n {\n path: \"resources\",\n i18nKey: \"devportal.nav.resources\",\n fallback: \"Resources\",\n icon: Library,\n },\n {\n path: \"publisher/profile\",\n i18nKey: \"devportal.nav.publisher\",\n fallback: \"Publisher\",\n icon: User,\n matchPrefixes: [\"publisher\"],\n },\n {\n path: \"settings\",\n i18nKey: \"devportal.nav.settings\",\n fallback: \"Settings\",\n icon: Settings,\n },\n];\n\nfunction joinBaseAndPath(basePath: string | undefined, path: string): string {\n const base = (basePath ?? \"\").replace(/\\/$/, \"\");\n if (!path) return base || \"/\";\n const suffix = path.startsWith(\"/\") ? path : `/${path}`;\n return `${base}${suffix}`;\n}\n\nfunction isSectionActive(\n pathname: string,\n basePath: string | undefined,\n section: SectionDef,\n): boolean {\n const sectionUrl = joinBaseAndPath(basePath, section.path);\n // Index/dashboard is active only when exactly matched (or with empty extra).\n if (section.path === \"\") {\n return pathname === sectionUrl || pathname === `${sectionUrl}/`;\n }\n const candidates = [section.path, ...(section.matchPrefixes ?? [])];\n return candidates.some((prefix) => {\n const url = joinBaseAndPath(basePath, prefix);\n return pathname === url || pathname.startsWith(`${url}/`);\n });\n}\n\n/**\n * Org context switcher — can be embedded standalone or inside SectionNav.\n *\n * Shared between the regular devportal and the seller portal: filters the\n * org list to PHYSICAL-kind orgs under /devportal/seller/** and DIGITAL-kind\n * everywhere else, and reads/writes the matching active-org slot\n * (activePhysicalOrgId vs activeOrgId) so this switcher and\n * useSellerOrganization (used by the item-creation flow) always agree on\n * which org is current. See DeveloperOrgKind (BOFF-7285).\n */\nexport const OrgSwitcher: FC = () => {\n const {\n activeOrgId,\n setActiveOrgId,\n activePhysicalOrgId,\n setActivePhysicalOrgId,\n navigate,\n basePath,\n } = useDevportal();\n const isSeller = useIsSellerSection();\n const currentOrgId = isSeller ? activePhysicalOrgId : activeOrgId;\n const setCurrentOrgId = isSeller ? setActivePhysicalOrgId : setActiveOrgId;\n const tr = useTr();\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n const { data } = useGetMyOrganizationsQuery({ fetchPolicy: \"cache-first\" });\n const allOrgs: OrgItem[] = data?.myDeveloperOrganizations ?? [];\n const orgs = allOrgs.filter((org) =>\n isSeller ? org.kind === \"PHYSICAL\" : org.kind !== \"PHYSICAL\",\n );\n\n // Auto-select when there's exactly one matching org and nothing is stored yet\n useEffect(() => {\n if (!currentOrgId && orgs.length === 1 && orgs[0]?.id) {\n setCurrentOrgId(orgs[0].id);\n }\n }, [orgs, currentOrgId, setCurrentOrgId]);\n\n // Close on outside click\n useEffect(() => {\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n if (open) document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n const activeOrg = orgs.find((o) => o.id === currentOrgId);\n const label =\n activeOrg?.name ??\n (orgs.length === 0\n ? tr(\"devportal.nav.noOrg\", \"No organization\")\n : tr(\"devportal.nav.selectOrg\", \"Select org\"));\n\n const createOrgPath = orgSectionPath(isSeller, \"new\");\n\n return (\n <div ref={ref} className=\"relative flex-shrink-0\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium transition-colors\",\n \"bg-bg-surface text-text-primary border-border-subtle hover:bg-accent\",\n )}\n aria-label={tr(\"devportal.nav.switchOrg\", \"Switch organization\")}\n >\n <Building2 size={13} className=\"text-primary flex-shrink-0\" />\n <span className=\"max-w-[140px] truncate\">{label}</span>\n <ChevronDown\n size={13}\n className={cn(\"transition-transform\", open && \"rotate-180\")}\n />\n </button>\n\n {open && (\n <div className=\"absolute right-0 top-full z-50 mt-1 min-w-[200px] rounded-md border border-border-subtle bg-popover shadow-lg py-1\">\n {orgs.map((org) => (\n <button\n key={org.id}\n type=\"button\"\n onClick={() => {\n setCurrentOrgId(org.id);\n setOpen(false);\n }}\n className={cn(\n \"flex w-full items-center gap-2 px-3 py-2 text-sm text-left transition-colors hover:bg-accent\",\n org.id === currentOrgId\n ? \"text-primary font-medium\"\n : \"text-text-primary\",\n )}\n >\n <Check\n size={13}\n className={cn(\n \"flex-shrink-0\",\n org.id === currentOrgId\n ? \"opacity-100 text-primary\"\n : \"opacity-0\",\n )}\n />\n <span className=\"truncate\">{org.name}</span>\n </button>\n ))}\n {orgs.length > 0 && (\n <div className=\"my-1 border-t border-border-subtle\" />\n )}\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n navigate?.(`${basePath ?? \"\"}${createOrgPath}`);\n }}\n className=\"flex w-full items-center gap-2 px-3 py-2 text-sm text-left text-primary transition-colors hover:bg-accent\"\n >\n <Plus size={13} className=\"flex-shrink-0\" />\n <span className=\"truncate\">\n {tr(\"devportal.nav.newOrganization\", \"New organization\")}\n </span>\n </button>\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Horizontal section nav rendered above the page content on every devportal\n * route. Gives developers a one-click jump between all top-level sections so\n * routes like OAuth, Delegations, Analytics, Revenue, Docs, Resources,\n * Publisher Profile, and Settings are reachable without typing URLs.\n *\n * Renders nothing when `basePath` is undefined (standalone/dev mode) so it\n * doesn't conflict with whatever harness wraps the MFE there.\n */\nexport const SectionNav: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { pathname } = useLocation();\n const tr = useTr();\n\n if (!basePath || !navigate) return null;\n\n const handleClick = (path: string) => {\n navigate(joinBaseAndPath(basePath, path));\n };\n\n return (\n <nav\n aria-label={tr(\"devportal.nav.sections\", \"Developer portal sections\")}\n className=\"border-b border-border-subtle bg-bg-surface/40 px-4 py-2\"\n data-testid=\"devportal-section-nav\"\n >\n <div className=\"flex items-center gap-2\">\n <ul className=\"flex flex-1 flex-wrap gap-1\">\n {SECTIONS.map((section) => {\n const active = isSectionActive(pathname, basePath, section);\n const Icon = section.icon;\n return (\n <li key={section.path}>\n <button\n type=\"button\"\n onClick={() => handleClick(section.path)}\n aria-current={active ? \"page\" : undefined}\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors\",\n active\n ? \"bg-action-primary-bg text-action-primary-text\"\n : \"text-text-secondary hover:bg-accent hover:text-text-primary\",\n )}\n >\n <Icon size={14} />\n <span>{tr(section.i18nKey, section.fallback)}</span>\n </button>\n </li>\n );\n })}\n </ul>\n <OrgSwitcher />\n </div>\n </nav>\n );\n};\n\n// Exported for unit tests that want to assert against the canonical list.\nexport const __SECTION_NAV_SECTIONS = SECTIONS;\n"],"mappings":";;;;;;;;;;;AAoIA,IAAa,UAAwB;CACnC,IAAM,EACJ,gBACA,mBACA,wBACA,2BACA,aACA,gBACE,GAAc,EACZ,IAAW,GAAoB,EAC/B,IAAe,IAAW,IAAsB,GAChD,IAAkB,IAAW,IAAyB,GACtD,IAAK,GAAO,EACZ,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,IAAM,EAAuB,KAAK,EAElC,EAAE,YAAS,EAA2B,EAAE,aAAa,eAAe,CAAC,EAErE,KADqB,GAAM,4BAA4B,EAAE,EAC1C,QAAQ,MAC3B,IAAW,EAAI,SAAS,aAAa,EAAI,SAAS,WACnD;AAUD,CAPA,QAAgB;AACd,EAAI,CAAC,KAAgB,EAAK,WAAW,KAAK,EAAK,IAAI,MACjD,EAAgB,EAAK,GAAG,GAAG;IAE5B;EAAC;EAAM;EAAc;EAAgB,CAAC,EAGzC,QAAgB;EACd,IAAM,KAAW,MAAkB;AACjC,GAAI,EAAI,WAAW,CAAC,EAAI,QAAQ,SAAS,EAAE,OAAe,IACxD,EAAQ,GAAM;;AAIlB,SADI,KAAM,SAAS,iBAAiB,aAAa,EAAQ,QAC5C,SAAS,oBAAoB,aAAa,EAAQ;IAC9D,CAAC,EAAK,CAAC;CAGV,IAAM,IADY,EAAK,MAAM,MAAM,EAAE,OAAO,EAAa,EAE5C,SACV,EAAK,WAAW,IACb,EAAG,uBAAuB,kBAAkB,GAC5C,EAAG,2BAA2B,aAAa,GAE3C,IAAgB,EAAe,GAAU,MAAM;AAErD,QACE,kBAAC,OAAD;EAAU;EAAK,WAAU;YAAzB,CACE,kBAAC,UAAD;GACE,MAAK;GACL,eAAe,GAAS,MAAM,CAAC,EAAE;GACjC,WAAW,EACT,wGACA,uEACD;GACD,cAAY,EAAG,2BAA2B,sBAAsB;aAPlE;IASE,kBAAC,GAAD;KAAW,MAAM;KAAI,WAAU;KAA+B,CAAA;IAC9D,kBAAC,QAAD;KAAM,WAAU;eAA0B;KAAa,CAAA;IACvD,kBAAC,GAAD;KACE,MAAM;KACN,WAAW,EAAG,wBAAwB,KAAQ,aAAa;KAC3D,CAAA;IACK;MAER,KACC,kBAAC,OAAD;GAAK,WAAU;aAAf;IACG,EAAK,KAAK,MACT,kBAAC,UAAD;KAEE,MAAK;KACL,eAAe;AAEb,MADA,EAAgB,EAAI,GAAG,EACvB,EAAQ,GAAM;;KAEhB,WAAW,EACT,gGACA,EAAI,OAAO,IACP,6BACA,oBACL;eAZH,CAcE,kBAAC,GAAD;MACE,MAAM;MACN,WAAW,EACT,iBACA,EAAI,OAAO,IACP,6BACA,YACL;MACD,CAAA,EACF,kBAAC,QAAD;MAAM,WAAU;gBAAY,EAAI;MAAY,CAAA,CACrC;OAvBF,EAAI,GAuBF,CACT;IACD,EAAK,SAAS,KACb,kBAAC,OAAD,EAAK,WAAU,sCAAuC,CAAA;IAExD,kBAAC,UAAD;KACE,MAAK;KACL,eAAe;AAEb,MADA,EAAQ,GAAM,EACd,IAAW,GAAG,KAAY,KAAK,IAAgB;;KAEjD,WAAU;eANZ,CAQE,kBAAC,GAAD;MAAM,MAAM;MAAI,WAAU;MAAkB,CAAA,EAC5C,kBAAC,QAAD;MAAM,WAAU;gBACb,EAAG,iCAAiC,mBAAmB;MACnD,CAAA,CACA;;IACL;KAEJ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when the current route is under the seller portal
|
|
3
|
+
* (/devportal/seller/**). The organization-level pages (Organizations list,
|
|
4
|
+
* Organization Detail, Create Organization, Members, Revenue) are shared
|
|
5
|
+
* between the regular devportal and the seller portal — this is the single
|
|
6
|
+
* signal they use to decide whether to operate on PHYSICAL-kind orgs
|
|
7
|
+
* (seller) or DIGITAL-kind orgs (everywhere else), so the flag/kind check
|
|
8
|
+
* only has to be made in one place. See DeveloperOrgKind (BOFF-7285).
|
|
9
|
+
*/
|
|
10
|
+
export declare function useIsSellerSection(): boolean;
|
|
11
|
+
/** `/seller/organizations` when in the seller portal, `/organizations` otherwise. */
|
|
12
|
+
export declare function orgSectionPath(isSeller: boolean, suffix?: string): string;
|
|
13
|
+
//# sourceMappingURL=useIsSellerSection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsSellerSection.d.ts","sourceRoot":"","sources":["../../../src/devportal/hooks/useIsSellerSection.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAW5C;AAED,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAK,GAAG,MAAM,CAGrE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useDevportal as e } from "../providers/DevportalProvider.js";
|
|
2
|
+
import { useLocation as t } from "react-router";
|
|
3
|
+
//#region src/devportal/hooks/useIsSellerSection.ts
|
|
4
|
+
function n() {
|
|
5
|
+
let { pathname: n } = t(), { basePath: r } = e(), i = `${(r ?? "").replace(/\/$/, "")}/seller`;
|
|
6
|
+
return n === i || n.startsWith(`${i}/`) || n === "/seller" || n.startsWith("/seller/");
|
|
7
|
+
}
|
|
8
|
+
function r(e, t = "") {
|
|
9
|
+
let n = e ? "/seller/organizations" : "/organizations";
|
|
10
|
+
return t ? `${n}${t.startsWith("/") ? "" : "/"}${t}` : n;
|
|
11
|
+
}
|
|
12
|
+
//#endregion
|
|
13
|
+
export { r as orgSectionPath, n as useIsSellerSection };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=useIsSellerSection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsSellerSection.js","names":[],"sources":["../../../src/devportal/hooks/useIsSellerSection.ts"],"sourcesContent":["import { useLocation } from \"react-router\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\n\n/**\n * True when the current route is under the seller portal\n * (/devportal/seller/**). The organization-level pages (Organizations list,\n * Organization Detail, Create Organization, Members, Revenue) are shared\n * between the regular devportal and the seller portal — this is the single\n * signal they use to decide whether to operate on PHYSICAL-kind orgs\n * (seller) or DIGITAL-kind orgs (everywhere else), so the flag/kind check\n * only has to be made in one place. See DeveloperOrgKind (BOFF-7285).\n */\nexport function useIsSellerSection(): boolean {\n const { pathname } = useLocation();\n const { basePath } = useDevportal();\n const base = (basePath ?? \"\").replace(/\\/$/, \"\");\n const prefixed = `${base}/seller`;\n return (\n pathname === prefixed ||\n pathname.startsWith(`${prefixed}/`) ||\n pathname === \"/seller\" ||\n pathname.startsWith(\"/seller/\")\n );\n}\n\n/** `/seller/organizations` when in the seller portal, `/organizations` otherwise. */\nexport function orgSectionPath(isSeller: boolean, suffix = \"\"): string {\n const base = isSeller ? \"/seller/organizations\" : \"/organizations\";\n return suffix ? `${base}${suffix.startsWith(\"/\") ? \"\" : \"/\"}${suffix}` : base;\n}\n"],"mappings":";;;AAYA,SAAgB,IAA8B;CAC5C,IAAM,EAAE,gBAAa,GAAa,EAC5B,EAAE,gBAAa,GAAc,EAE7B,IAAW,IADH,KAAY,IAAI,QAAQ,OAAO,GAAG,CACvB;AACzB,QACE,MAAa,KACb,EAAS,WAAW,GAAG,EAAS,GAAG,IACnC,MAAa,aACb,EAAS,WAAW,WAAW;;AAKnC,SAAgB,EAAe,GAAmB,IAAS,IAAY;CACrE,IAAM,IAAO,IAAW,0BAA0B;AAClD,QAAO,IAAS,GAAG,IAAO,EAAO,WAAW,IAAI,GAAG,KAAK,MAAM,MAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CreateOrganizationPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"CreateOrganizationPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/CreateOrganizationPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAoChC;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,EA6VpC,CAAC"}
|
|
@@ -1,86 +1,87 @@
|
|
|
1
1
|
import { useDevportal as e } from "../providers/DevportalProvider.js";
|
|
2
2
|
import { useDevportalEventBus as t } from "../events/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { orgSectionPath as n, useIsSellerSection as r } from "../hooks/useIsSellerSection.js";
|
|
4
|
+
import { useCreateBillingAccountMutation as i, useCreateOrganizationMutation as a, useCreateSellerOrganizationMutation as o, useLinkDevOrgBillingAccountMutation as s } from "../../generated/global-operations.js";
|
|
5
|
+
import { PageLayout as c, PageSection as l } from "../components/PageLayout.js";
|
|
6
|
+
import { InputField as u, TextareaField as d } from "../components/FormField.js";
|
|
7
|
+
import { PermissionGuard as f } from "../components/PermissionGuard.js";
|
|
7
8
|
import "../components/index.js";
|
|
8
9
|
import "../hooks/index.js";
|
|
9
|
-
import { useState as
|
|
10
|
-
import { Building2 as
|
|
11
|
-
import { Fragment as
|
|
12
|
-
import { useI18n as
|
|
10
|
+
import { useState as p } from "react";
|
|
11
|
+
import { Building2 as m, Info as h, X as g } from "lucide-react";
|
|
12
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
13
|
+
import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
13
14
|
//#region src/devportal/pages/CreateOrganizationPage.tsx
|
|
14
|
-
var
|
|
15
|
-
let { navigate:
|
|
16
|
-
let n =
|
|
15
|
+
var x = () => {
|
|
16
|
+
let { navigate: x, basePath: S, currentUser: C, setActiveOrgId: w, setActivePhysicalOrgId: T } = e(), E = r(), { t: D } = b(), O = (e, t) => {
|
|
17
|
+
let n = D(e);
|
|
17
18
|
return n === e ? t : n;
|
|
18
|
-
}, [
|
|
19
|
+
}, [k, A] = p({}), [j, { loading: M }] = a(), [N, { loading: P }] = o(), F = E ? P : M, [I] = i(), [L] = s(), R = t(), [z, B] = p({
|
|
19
20
|
name: "",
|
|
20
21
|
slug: "",
|
|
21
22
|
description: "",
|
|
22
23
|
websiteUrl: "",
|
|
23
24
|
contactEmail: "",
|
|
24
25
|
supportEmail: ""
|
|
25
|
-
}),
|
|
26
|
-
|
|
27
|
-
},
|
|
26
|
+
}), V = (e) => {
|
|
27
|
+
x?.(`${S}${e}`);
|
|
28
|
+
}, H = (e) => e.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), U = (e) => {
|
|
28
29
|
let t = e.target.value;
|
|
29
|
-
|
|
30
|
+
B((e) => ({
|
|
30
31
|
...e,
|
|
31
32
|
name: t,
|
|
32
|
-
slug: e.slug ||
|
|
33
|
-
})),
|
|
33
|
+
slug: e.slug || H(t)
|
|
34
|
+
})), k.name && A((e) => ({
|
|
34
35
|
...e,
|
|
35
36
|
name: void 0
|
|
36
37
|
}));
|
|
37
|
-
},
|
|
38
|
-
|
|
38
|
+
}, W = (e, t) => {
|
|
39
|
+
B((n) => ({
|
|
39
40
|
...n,
|
|
40
41
|
[e]: t
|
|
41
|
-
})),
|
|
42
|
+
})), k[e] && A((t) => ({
|
|
42
43
|
...t,
|
|
43
44
|
[e]: void 0
|
|
44
45
|
}));
|
|
45
|
-
},
|
|
46
|
+
}, G = () => {
|
|
46
47
|
let e = {};
|
|
47
|
-
return
|
|
48
|
+
return z.name.trim() ? z.name.length < 2 ? e.name = O("devportal.orgNameTooShort", "Name must be at least 2 characters") : z.name.length > 100 && (e.name = O("devportal.nameTooLong", "Name must be less than 100 characters")) : e.name = O("devportal.orgNameRequired", "Organization name is required"), z.slug.trim() ? /^[a-z0-9-]+$/.test(z.slug) || (e.slug = O("devportal.slugInvalid", "Slug can only contain lowercase letters, numbers, and hyphens")) : e.slug = O("devportal.slugRequired", "Slug is required"), z.contactEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(z.contactEmail) && (e.contactEmail = O("devportal.invalidEmailAddress", "Invalid email address")), z.supportEmail && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(z.supportEmail) && (e.supportEmail = O("devportal.invalidEmailAddress", "Invalid email address")), A(e), Object.keys(e).length === 0;
|
|
48
49
|
};
|
|
49
|
-
return /* @__PURE__ */
|
|
50
|
+
return /* @__PURE__ */ v(f, {
|
|
50
51
|
authOnly: !0,
|
|
51
|
-
children: /* @__PURE__ */
|
|
52
|
-
title:
|
|
53
|
-
description:
|
|
54
|
-
purpose:
|
|
55
|
-
backLink: `${
|
|
56
|
-
backLabel:
|
|
57
|
-
children: /* @__PURE__ */
|
|
52
|
+
children: /* @__PURE__ */ v(c, {
|
|
53
|
+
title: O("devportal.createOrganization", "Create Organization"),
|
|
54
|
+
description: E ? O("devportal.createSellerOrganizationDescription", "Set up a seller organization to start selling physical products") : O("devportal.createOrganizationDescription", "Set up a developer organization to collaborate with your team"),
|
|
55
|
+
purpose: E ? O("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.") : O("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."),
|
|
56
|
+
backLink: `${S}${n(E)}`,
|
|
57
|
+
backLabel: O("devportal.backToOrganizations", "Back to Organizations"),
|
|
58
|
+
children: /* @__PURE__ */ y("form", {
|
|
58
59
|
onSubmit: async (e) => {
|
|
59
|
-
if (e.preventDefault(),
|
|
60
|
-
let e =
|
|
61
|
-
name:
|
|
62
|
-
slug:
|
|
63
|
-
description:
|
|
64
|
-
websiteUrl:
|
|
65
|
-
contactEmail:
|
|
66
|
-
supportEmail:
|
|
67
|
-
} } })).data?.createDeveloperOrganization?.id;
|
|
68
|
-
if (
|
|
69
|
-
|
|
70
|
-
organizationId:
|
|
71
|
-
name:
|
|
72
|
-
});
|
|
60
|
+
if (e.preventDefault(), G()) try {
|
|
61
|
+
let e = {
|
|
62
|
+
name: z.name,
|
|
63
|
+
slug: z.slug || void 0,
|
|
64
|
+
description: z.description || void 0,
|
|
65
|
+
websiteUrl: z.websiteUrl || void 0,
|
|
66
|
+
contactEmail: z.contactEmail || void 0,
|
|
67
|
+
supportEmail: z.supportEmail || void 0
|
|
68
|
+
}, t = E ? (await N({ variables: { input: e } })).data?.createSellerOrganization?.id : (await j({ variables: { input: e } })).data?.createDeveloperOrganization?.id;
|
|
69
|
+
if (t) {
|
|
70
|
+
R.emit("devportal.org.created", {
|
|
71
|
+
organizationId: t,
|
|
72
|
+
name: z.name
|
|
73
|
+
}), E ? T(t) : w(t);
|
|
73
74
|
try {
|
|
74
|
-
let
|
|
75
|
-
name:
|
|
76
|
-
email:
|
|
75
|
+
let e = (await I({ variables: { input: {
|
|
76
|
+
name: z.name,
|
|
77
|
+
email: C?.email ?? ""
|
|
77
78
|
} } })).data?.createBillingAccount?.id;
|
|
78
|
-
|
|
79
|
-
organizationId:
|
|
80
|
-
billingAccountId:
|
|
79
|
+
e && await L({ variables: {
|
|
80
|
+
organizationId: t,
|
|
81
|
+
billingAccountId: e
|
|
81
82
|
} });
|
|
82
83
|
} catch {}
|
|
83
|
-
|
|
84
|
+
V(n(E, t));
|
|
84
85
|
}
|
|
85
86
|
} catch (e) {
|
|
86
87
|
console.error("Failed to create organization:", e);
|
|
@@ -88,96 +89,96 @@ var v = () => {
|
|
|
88
89
|
},
|
|
89
90
|
className: "space-y-8 max-w-3xl",
|
|
90
91
|
children: [
|
|
91
|
-
/* @__PURE__ */
|
|
92
|
-
title:
|
|
93
|
-
description:
|
|
94
|
-
children: /* @__PURE__ */
|
|
92
|
+
/* @__PURE__ */ v(l, {
|
|
93
|
+
title: O("devportal.organizationDetails", "Organization Details"),
|
|
94
|
+
description: O("devportal.organizationDetailsDescription", "Basic information about your organization"),
|
|
95
|
+
children: /* @__PURE__ */ y("div", {
|
|
95
96
|
className: "space-y-4",
|
|
96
97
|
children: [
|
|
97
|
-
/* @__PURE__ */
|
|
98
|
-
label:
|
|
99
|
-
value:
|
|
100
|
-
onChange:
|
|
101
|
-
placeholder:
|
|
98
|
+
/* @__PURE__ */ v(u, {
|
|
99
|
+
label: O("devportal.organizationName", "Organization Name"),
|
|
100
|
+
value: z.name,
|
|
101
|
+
onChange: U,
|
|
102
|
+
placeholder: O("devportal.organizationNamePlaceholder", "Acme Development"),
|
|
102
103
|
required: !0,
|
|
103
|
-
error:
|
|
104
|
-
hint:
|
|
104
|
+
error: k.name,
|
|
105
|
+
hint: O("devportal.organizationNameHint", "Your organization's display name")
|
|
105
106
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
label:
|
|
108
|
-
value:
|
|
109
|
-
onChange: (e) =>
|
|
110
|
-
placeholder:
|
|
107
|
+
/* @__PURE__ */ v(u, {
|
|
108
|
+
label: O("devportal.slug", "Slug"),
|
|
109
|
+
value: z.slug,
|
|
110
|
+
onChange: (e) => W("slug", e.target.value.toLowerCase()),
|
|
111
|
+
placeholder: O("devportal.orgSlugPlaceholder", "acme-dev"),
|
|
111
112
|
required: !0,
|
|
112
|
-
error:
|
|
113
|
-
hint:
|
|
113
|
+
error: k.slug,
|
|
114
|
+
hint: O("devportal.slugHint", "URL-friendly identifier (auto-generated from name)")
|
|
114
115
|
}),
|
|
115
|
-
/* @__PURE__ */
|
|
116
|
-
label:
|
|
117
|
-
value:
|
|
118
|
-
onChange: (e) =>
|
|
119
|
-
placeholder:
|
|
116
|
+
/* @__PURE__ */ v(d, {
|
|
117
|
+
label: O("devportal.description", "Description"),
|
|
118
|
+
value: z.description,
|
|
119
|
+
onChange: (e) => W("description", e.target.value),
|
|
120
|
+
placeholder: O("devportal.orgDescriptionPlaceholder", "Tell us about your organization..."),
|
|
120
121
|
rows: 3
|
|
121
122
|
}),
|
|
122
|
-
/* @__PURE__ */
|
|
123
|
-
label:
|
|
123
|
+
/* @__PURE__ */ v(u, {
|
|
124
|
+
label: O("devportal.websiteUrl", "Website URL"),
|
|
124
125
|
type: "url",
|
|
125
|
-
value:
|
|
126
|
-
onChange: (e) =>
|
|
126
|
+
value: z.websiteUrl,
|
|
127
|
+
onChange: (e) => W("websiteUrl", e.target.value),
|
|
127
128
|
placeholder: "https://example.com"
|
|
128
129
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
130
|
+
/* @__PURE__ */ y("div", {
|
|
130
131
|
className: "grid gap-4 sm:grid-cols-2",
|
|
131
|
-
children: [/* @__PURE__ */
|
|
132
|
-
label:
|
|
132
|
+
children: [/* @__PURE__ */ v(u, {
|
|
133
|
+
label: O("devportal.contactEmail", "Contact Email"),
|
|
133
134
|
type: "email",
|
|
134
|
-
value:
|
|
135
|
-
onChange: (e) =>
|
|
135
|
+
value: z.contactEmail,
|
|
136
|
+
onChange: (e) => W("contactEmail", e.target.value),
|
|
136
137
|
placeholder: "contact@example.com",
|
|
137
|
-
error:
|
|
138
|
-
}), /* @__PURE__ */
|
|
139
|
-
label:
|
|
138
|
+
error: k.contactEmail
|
|
139
|
+
}), /* @__PURE__ */ v(u, {
|
|
140
|
+
label: O("devportal.supportEmail", "Support Email"),
|
|
140
141
|
type: "email",
|
|
141
|
-
value:
|
|
142
|
-
onChange: (e) =>
|
|
142
|
+
value: z.supportEmail,
|
|
143
|
+
onChange: (e) => W("supportEmail", e.target.value),
|
|
143
144
|
placeholder: "support@example.com",
|
|
144
|
-
error:
|
|
145
|
+
error: k.supportEmail
|
|
145
146
|
})]
|
|
146
147
|
})
|
|
147
148
|
]
|
|
148
149
|
})
|
|
149
150
|
}),
|
|
150
|
-
/* @__PURE__ */
|
|
151
|
+
/* @__PURE__ */ y("div", {
|
|
151
152
|
className: "rounded-lg border border-border-subtle bg-status-info-bg-subtle p-4 flex gap-3",
|
|
152
|
-
children: [/* @__PURE__ */ h
|
|
153
|
+
children: [/* @__PURE__ */ v(h, {
|
|
153
154
|
size: 20,
|
|
154
155
|
className: "text-accent-blue flex-shrink-0 mt-0.5"
|
|
155
|
-
}), /* @__PURE__ */
|
|
156
|
+
}), /* @__PURE__ */ y("div", {
|
|
156
157
|
className: "text-sm text-status-info-text",
|
|
157
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ v("p", {
|
|
158
159
|
className: "font-medium",
|
|
159
|
-
children:
|
|
160
|
-
}), /* @__PURE__ */
|
|
160
|
+
children: O("devportal.billingAutoSetup", "A billing account will be automatically set up")
|
|
161
|
+
}), /* @__PURE__ */ v("p", {
|
|
161
162
|
className: "mt-1",
|
|
162
|
-
children:
|
|
163
|
+
children: O("devportal.billingAutoSetupNote", "Revenue from app sales will be credited to it. You can complete legal and tax details for payouts later in Organization Settings.")
|
|
163
164
|
})]
|
|
164
165
|
})]
|
|
165
166
|
}),
|
|
166
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ y("div", {
|
|
167
168
|
className: "flex items-center justify-end gap-3 border-t pt-6",
|
|
168
|
-
children: [/* @__PURE__ */
|
|
169
|
+
children: [/* @__PURE__ */ y("button", {
|
|
169
170
|
type: "button",
|
|
170
171
|
onClick: () => {
|
|
171
|
-
|
|
172
|
+
V(n(E));
|
|
172
173
|
},
|
|
173
|
-
disabled:
|
|
174
|
+
disabled: F,
|
|
174
175
|
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",
|
|
175
|
-
children: [/* @__PURE__ */
|
|
176
|
-
}), /* @__PURE__ */
|
|
176
|
+
children: [/* @__PURE__ */ v(g, { size: 16 }), O("devportal.cancel", "Cancel")]
|
|
177
|
+
}), /* @__PURE__ */ v("button", {
|
|
177
178
|
type: "submit",
|
|
178
|
-
disabled:
|
|
179
|
+
disabled: F,
|
|
179
180
|
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",
|
|
180
|
-
children:
|
|
181
|
+
children: F ? /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("span", { className: "h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" }), O("devportal.creating", "Creating...")] }) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v(m, { size: 16 }), O("devportal.createOrganization", "Create Organization")] })
|
|
181
182
|
})]
|
|
182
183
|
})
|
|
183
184
|
]
|
|
@@ -186,6 +187,6 @@ var v = () => {
|
|
|
186
187
|
});
|
|
187
188
|
};
|
|
188
189
|
//#endregion
|
|
189
|
-
export {
|
|
190
|
+
export { x as CreateOrganizationPage };
|
|
190
191
|
|
|
191
192
|
//# sourceMappingURL=CreateOrganizationPage.js.map
|