Skip to content

Commit 8819e25

Browse files
authored
fix(webapp): hard-navigate after creating an organization (#4530)
1 parent 336f515 commit 8819e25

2 files changed

Lines changed: 36 additions & 8 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Creating an organization sometimes left you back on the creation form even though the organization had already been created, so clicking Create again made a duplicate. Creating an organization now completes and takes you to your new organization.

apps/webapp/app/routes/_app.orgs.new/route.tsx

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ import { GlobeLinesIcon } from "~/assets/icons/GlobeLinesIcon";
33
import { parseWithZod } from "@conform-to/zod";
44
import { BuildingOffice2Icon } from "@heroicons/react/20/solid";
55
import { RadioGroup } from "@radix-ui/react-radio-group";
6-
import { json, redirect, type ActionFunction, type LoaderFunctionArgs } from "@remix-run/node";
6+
import {
7+
json,
8+
redirectDocument,
9+
type ActionFunctionArgs,
10+
type LoaderFunctionArgs,
11+
} from "@remix-run/node";
712
import { Form, useActionData, useNavigation } from "@remix-run/react";
813
import { useState } from "react";
914
import { typedjson, useTypedLoaderData } from "remix-typedjson";
@@ -24,6 +29,7 @@ import { useFaviconUrl } from "~/hooks/useFaviconUrl";
2429
import { useFeatures } from "~/hooks/useFeatures";
2530
import { createOrganization } from "~/models/organization.server";
2631
import { NewOrganizationPresenter } from "~/presenters/NewOrganizationPresenter.server";
32+
import { logger } from "~/services/logger.server";
2733
import { requireUser, requireUserId } from "~/services/session.server";
2834
import { extractDomain, faviconUrl } from "~/utils/favicon";
2935
import { organizationPath, rootPath } from "~/utils/pathBuilder";
@@ -47,7 +53,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
4753
});
4854
};
4955

50-
export const action: ActionFunction = async ({ request }) => {
56+
export const action = async ({ request }: ActionFunctionArgs) => {
5157
const user = await requireUser(request);
5258
const formData = await request.formData();
5359
const submission = parseWithZod(formData, { schema });
@@ -102,18 +108,32 @@ export const action: ActionFunction = async ({ request }) => {
102108
if (next) {
103109
params.set("next", next);
104110
}
105-
return redirect(`${organizationPath(organization)}/projects/new?${params.toString()}`);
111+
return redirectDocument(
112+
`${organizationPath(organization)}/projects/new?${params.toString()}`
113+
);
106114
}
107115

108-
return redirect(organizationPath(organization));
109-
} catch (error: any) {
110-
return json({ errors: { body: error.message } }, { status: 400 });
116+
return redirectDocument(organizationPath(organization));
117+
} catch (error) {
118+
logger.error("Failed to create organization", {
119+
userId: user.id,
120+
error: error instanceof Error ? error.message : error,
121+
});
122+
123+
return json(
124+
submission.reply({
125+
formErrors: [
126+
"We couldn't create your organization. Check your organization list before trying again, and if this problem persists please contact support.",
127+
],
128+
}),
129+
{ status: 400 }
130+
);
111131
}
112132
};
113133

114134
export default function NewOrganizationPage() {
115135
const { hasOrganizations } = useTypedLoaderData<typeof loader>();
116-
const lastSubmission = useActionData();
136+
const lastSubmission = useActionData<typeof action>();
117137
const { isManagedCloud } = useFeatures();
118138
const navigation = useNavigation();
119139
const [companyUrl, setCompanyUrl] = useState("");
@@ -122,7 +142,7 @@ export default function NewOrganizationPage() {
122142

123143
const [form, { orgName }] = useForm({
124144
id: "create-organization",
125-
lastResult: lastSubmission as any,
145+
lastResult: lastSubmission,
126146
onValidate({ formData }) {
127147
return parseWithZod(formData, { schema });
128148
},
@@ -228,6 +248,8 @@ export default function NewOrganizationPage() {
228248
</>
229249
)}
230250

251+
<FormError id={form.errorId}>{form.errors}</FormError>
252+
231253
<FormButtons
232254
confirmButton={
233255
<Button type="submit" variant={"primary/small"} isLoading={isLoading}>

0 commit comments

Comments
 (0)