MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / CreateOrgPage

Function CreateOrgPage

apps/cloud/src/web/pages/create-org.tsx:43–154  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

41};
42
43export const CreateOrgPage = () => {
44 const auth = useAuth();
45 const navigate = useNavigate();
46 const invitationsResult = useAtomValue(pendingInvitationsAtom);
47 const doAccept = useAtomSet(acceptInvitation, { mode: "promiseExit" });
48
49 const [acceptingId, setAcceptingId] = useState<string | null>(null);
50 const [errorByInvitationId, setErrorByInvitationId] = useState<Record<string, string>>({});
51
52 const handleAccept = async (invitation: PendingInvitation) => {
53 setAcceptingId(invitation.id);
54 setErrorByInvitationId((prev) => {
55 if (!(invitation.id in prev)) return prev;
56 const next = { ...prev };
57 delete next[invitation.id];
58 return next;
59 });
60 const exit = await doAccept({
61 payload: { invitationId: invitation.id },
62 reactivityKeys: authWriteKeys,
63 });
64 setAcceptingId(null);
65 trackEvent("org_invitation_accepted", { success: Exit.isSuccess(exit) });
66 if (!Exit.isSuccess(exit)) {
67 setErrorByInvitationId((prev) => ({
68 ...prev,
69 [invitation.id]: "Couldn't accept this invitation. Try again or ask the inviter to resend.",
70 }));
71 }
72 };
73
74 const suggestedName =
75 auth.status === "authenticated" && auth.user.name != null && auth.user.name.trim() !== ""
76 ? `${auth.user.name}'s Organization`
77 : "";
78
79 const form = useCreateOrganizationForm({
80 defaultName: suggestedName,
81 onSuccess: () => {
82 void navigate({ to: "/setup-mcp" });
83 },
84 });
85
86 // Almost no new user has a pending invitation, so we never show a loading
87 // placeholder for them — the create form renders immediately and stays put.
88 // Invitations (when they exist) just appear above it once the fetch resolves;
89 // a refetch (the create-org submit invalidates the auth-keyed atom) keeps the
90 // last value, so nothing flickers.
91 const invitations = AsyncResult.match(invitationsResult, {
92 onInitial: () => [] as readonly PendingInvitation[],
93 onFailure: () => [] as readonly PendingInvitation[],
94 onSuccess: ({ value }) => value.invitations,
95 });
96
97 const count = invitations.length;
98 const sole = count === 1 ? invitations[0]! : null;
99
100 return (

Callers

nothing calls this directly

Calls 4

useAuthFunction · 0.90
handleAcceptFunction · 0.85
fetchFunction · 0.50

Tested by

no test coverage detected