@@ -3,7 +3,12 @@ import { GlobeLinesIcon } from "~/assets/icons/GlobeLinesIcon";
33import { parseWithZod } from "@conform-to/zod" ;
44import { BuildingOffice2Icon } from "@heroicons/react/20/solid" ;
55import { 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" ;
712import { Form , useActionData , useNavigation } from "@remix-run/react" ;
813import { useState } from "react" ;
914import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
@@ -24,6 +29,7 @@ import { useFaviconUrl } from "~/hooks/useFaviconUrl";
2429import { useFeatures } from "~/hooks/useFeatures" ;
2530import { createOrganization } from "~/models/organization.server" ;
2631import { NewOrganizationPresenter } from "~/presenters/NewOrganizationPresenter.server" ;
32+ import { logger } from "~/services/logger.server" ;
2733import { requireUser , requireUserId } from "~/services/session.server" ;
2834import { extractDomain , faviconUrl } from "~/utils/favicon" ;
2935import { 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
114134export 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