@@ -13,7 +13,6 @@ import {
1313 Success16Icon ,
1414 FieldTitle ,
1515} from '@oxide/ui'
16- import type { Project } from '@oxide/api'
1716import { useApiMutation , useApiQueryClient } from '@oxide/api'
1817import { useParams , useToast } from '../hooks'
1918import { getServerError } from '../util/errors'
@@ -24,105 +23,91 @@ const ERROR_CODES = {
2423 'A project with that name already exists in this organization' ,
2524}
2625
27- // exists primarily so we can test it without worrying about route params
28- export function ProjectCreateForm ( {
29- orgName,
30- onSuccess,
31- } : {
32- orgName : string
33- onSuccess : ( p : Project ) => void
34- } ) {
35- const createProject = useApiMutation ( 'organizationProjectsPost' , {
36- onSuccess,
37- } )
38- return (
39- < Formik
40- initialValues = { { name : '' , description : '' } }
41- onSubmit = { ( { name, description } ) => {
42- createProject . mutate ( {
43- organizationName : orgName ,
44- body : { name, description } ,
45- } )
46- } }
47- >
48- < Form >
49- < div className = "mb-4" >
50- < FieldTitle htmlFor = "project-name" > Choose a name</ FieldTitle >
51- < TextField
52- id = "project-name"
53- name = "name"
54- placeholder = "Enter name"
55- validate = { validateName }
56- autoComplete = "off"
57- />
58- < TextFieldError name = "name" />
59- </ div >
60- < div className = "mb-8" >
61- < FieldTitle htmlFor = "project-description" >
62- Choose a description
63- </ FieldTitle >
64- < TextFieldHint id = "description-hint" >
65- What is unique about your project?
66- </ TextFieldHint >
67- < TextField
68- id = "project-description"
69- name = "description"
70- aria-describedby = "description-hint"
71- placeholder = "A project"
72- autoComplete = "off"
73- />
74- </ div >
75- < Button
76- type = "submit"
77- variant = "dim"
78- className = "w-[30rem]"
79- disabled = { createProject . isLoading }
80- >
81- Create project
82- </ Button >
83- < div className = "text-red-500 mt-2" >
84- { getServerError ( createProject . error , ERROR_CODES ) }
85- </ div >
86- </ Form >
87- </ Formik >
88- )
89- }
90-
9126export default function ProjectCreatePage ( ) {
9227 const queryClient = useApiQueryClient ( )
9328 const addToast = useToast ( )
9429 const navigate = useNavigate ( )
9530
9631 const { orgName } = useParams ( 'orgName' )
32+
33+ const createProject = useApiMutation ( 'organizationProjectsPost' , {
34+ onSuccess ( project ) {
35+ // refetch list of projects in sidebar
36+ queryClient . invalidateQueries ( 'organizationProjectsGet' , {
37+ organizationName : orgName ,
38+ } )
39+ // avoid the project fetch when the project page loads since we have the data
40+ queryClient . setQueryData (
41+ 'organizationProjectsGetProject' ,
42+ { organizationName : orgName , projectName : project . name } ,
43+ project
44+ )
45+ addToast ( {
46+ icon : < Success16Icon /> ,
47+ title : 'Success!' ,
48+ content : 'Your project has been created.' ,
49+ timeout : 5000 ,
50+ } )
51+ navigate ( `../${ project . name } ` )
52+ } ,
53+ } )
54+
9755 return (
9856 < >
9957 < PageHeader >
10058 < PageTitle icon = { < Folder24Icon title = "Projects" /> } >
10159 Create a new project
10260 </ PageTitle >
10361 </ PageHeader >
104- < ProjectCreateForm
105- orgName = { orgName }
106- onSuccess = { ( project ) => {
107- // refetch list of projects in sidebar
108- queryClient . invalidateQueries ( 'organizationProjectsGet' , {
62+ < Formik
63+ initialValues = { { name : '' , description : '' } }
64+ onSubmit = { ( { name, description } ) => {
65+ createProject . mutate ( {
10966 organizationName : orgName ,
67+ body : { name, description } ,
11068 } )
111- // avoid the project fetch when the project page loads since we have the data
112- queryClient . setQueryData (
113- 'organizationProjectsGetProject' ,
114- { organizationName : orgName , projectName : project . name } ,
115- project
116- )
117- addToast ( {
118- icon : < Success16Icon /> ,
119- title : 'Success!' ,
120- content : 'Your project has been created.' ,
121- timeout : 5000 ,
122- } )
123- navigate ( `../${ project . name } ` )
12469 } }
125- />
70+ >
71+ < Form >
72+ < div className = "mb-4" >
73+ < FieldTitle htmlFor = "project-name" > Choose a name</ FieldTitle >
74+ < TextField
75+ id = "project-name"
76+ name = "name"
77+ placeholder = "Enter name"
78+ validate = { validateName }
79+ autoComplete = "off"
80+ />
81+ < TextFieldError name = "name" />
82+ </ div >
83+ < div className = "mb-8" >
84+ < FieldTitle htmlFor = "project-description" >
85+ Choose a description
86+ </ FieldTitle >
87+ < TextFieldHint id = "description-hint" >
88+ What is unique about your project?
89+ </ TextFieldHint >
90+ < TextField
91+ id = "project-description"
92+ name = "description"
93+ aria-describedby = "description-hint"
94+ placeholder = "A project"
95+ autoComplete = "off"
96+ />
97+ </ div >
98+ < Button
99+ type = "submit"
100+ variant = "dim"
101+ className = "w-[30rem]"
102+ disabled = { createProject . isLoading }
103+ >
104+ Create project
105+ </ Button >
106+ < div className = "text-red-500 mt-2" >
107+ { getServerError ( createProject . error , ERROR_CODES ) }
108+ </ div >
109+ </ Form >
110+ </ Formik >
126111 </ >
127112 )
128113}
0 commit comments