1+ import { useMutation , useQueryClient } from "@tanstack/react-query"
2+ import { Controller , type SubmitHandler , useForm } from "react-hook-form"
3+
14import {
25 Button ,
3- Checkbox ,
6+ DialogActionTrigger ,
7+ DialogTitle ,
48 Flex ,
5- FormControl ,
6- FormErrorMessage ,
7- FormLabel ,
89 Input ,
9- Modal ,
10- ModalBody ,
11- ModalCloseButton ,
12- ModalContent ,
13- ModalFooter ,
14- ModalHeader ,
15- ModalOverlay ,
10+ Text ,
11+ VStack ,
1612} from "@chakra-ui/react"
17- import { useMutation , useQueryClient } from "@tanstack/react-query"
18- import { type SubmitHandler , useForm } from "react-hook-form"
19-
13+ import { useState } from "react"
14+ import { FaPlus } from "react-icons/fa"
2015import { type UserCreate , UsersService } from "../../client"
2116import type { ApiError } from "../../client/core/ApiError"
2217import useCustomToast from "../../hooks/useCustomToast"
2318import { emailPattern , handleError } from "../../utils"
24-
25- interface AddUserProps {
26- isOpen : boolean
27- onClose : ( ) => void
28- }
19+ import { Checkbox } from "../ui/checkbox"
20+ import {
21+ DialogBody ,
22+ DialogCloseTrigger ,
23+ DialogContent ,
24+ DialogFooter ,
25+ DialogHeader ,
26+ DialogRoot ,
27+ DialogTrigger ,
28+ } from "../ui/dialog"
29+ import { Field } from "../ui/field"
2930
3031interface UserCreateForm extends UserCreate {
3132 confirm_password : string
3233}
3334
34- const AddUser = ( { isOpen, onClose } : AddUserProps ) => {
35+ const AddUser = ( ) => {
36+ const [ isOpen , setIsOpen ] = useState ( false )
3537 const queryClient = useQueryClient ( )
36- const showToast = useCustomToast ( )
38+ const { showSuccessToast } = useCustomToast ( )
3739 const {
40+ control,
3841 register,
3942 handleSubmit,
4043 reset,
4144 getValues,
42- formState : { errors, isSubmitting } ,
45+ formState : { errors, isValid , isSubmitting } ,
4346 } = useForm < UserCreateForm > ( {
4447 mode : "onBlur" ,
4548 criteriaMode : "all" ,
@@ -57,12 +60,12 @@ const AddUser = ({ isOpen, onClose }: AddUserProps) => {
5760 mutationFn : ( data : UserCreate ) =>
5861 UsersService . createUser ( { requestBody : data } ) ,
5962 onSuccess : ( ) => {
60- showToast ( "Success!" , " User created successfully." , "success ")
63+ showSuccessToast ( " User created successfully.")
6164 reset ( )
62- onClose ( )
65+ setIsOpen ( false )
6366 } ,
6467 onError : ( err : ApiError ) => {
65- handleError ( err , showToast )
68+ handleError ( err )
6669 } ,
6770 onSettled : ( ) => {
6871 queryClient . invalidateQueries ( { queryKey : [ "users" ] } )
@@ -74,108 +77,153 @@ const AddUser = ({ isOpen, onClose }: AddUserProps) => {
7477 }
7578
7679 return (
77- < >
78- < Modal
79- isOpen = { isOpen }
80- onClose = { onClose }
81- size = { { base : "sm" , md : "md" } }
82- isCentered
83- >
84- < ModalOverlay />
85- < ModalContent as = "form" onSubmit = { handleSubmit ( onSubmit ) } >
86- < ModalHeader > Add User</ ModalHeader >
87- < ModalCloseButton />
88- < ModalBody pb = { 6 } >
89- < FormControl isRequired isInvalid = { ! ! errors . email } >
90- < FormLabel htmlFor = "email" > Email</ FormLabel >
91- < Input
92- id = "email"
93- { ...register ( "email" , {
94- required : "Email is required" ,
95- pattern : emailPattern ,
96- } ) }
97- placeholder = "Email"
98- type = "email"
99- />
100- { errors . email && (
101- < FormErrorMessage > { errors . email . message } </ FormErrorMessage >
102- ) }
103- </ FormControl >
104- < FormControl mt = { 4 } isInvalid = { ! ! errors . full_name } >
105- < FormLabel htmlFor = "name" > Full name</ FormLabel >
106- < Input
107- id = "name"
108- { ...register ( "full_name" ) }
109- placeholder = "Full name"
110- type = "text"
111- />
112- { errors . full_name && (
113- < FormErrorMessage > { errors . full_name . message } </ FormErrorMessage >
114- ) }
115- </ FormControl >
116- < FormControl mt = { 4 } isRequired isInvalid = { ! ! errors . password } >
117- < FormLabel htmlFor = "password" > Set Password</ FormLabel >
118- < Input
119- id = "password"
120- { ...register ( "password" , {
121- required : "Password is required" ,
122- minLength : {
123- value : 8 ,
124- message : "Password must be at least 8 characters" ,
125- } ,
126- } ) }
127- placeholder = "Password"
128- type = "password"
80+ < DialogRoot
81+ size = { { base : "xs" , md : "md" } }
82+ placement = "center"
83+ open = { isOpen }
84+ onOpenChange = { ( { open } ) => setIsOpen ( open ) }
85+ >
86+ < DialogTrigger asChild >
87+ < Button value = "add-user" my = { 4 } >
88+ < FaPlus fontSize = "16px" />
89+ Add User
90+ </ Button >
91+ </ DialogTrigger >
92+ < DialogContent >
93+ < form onSubmit = { handleSubmit ( onSubmit ) } >
94+ < DialogHeader >
95+ < DialogTitle > Add User</ DialogTitle >
96+ </ DialogHeader >
97+ < DialogBody >
98+ < Text mb = { 4 } >
99+ Fill in the form below to add a new user to the system.
100+ </ Text >
101+ < VStack gap = { 4 } >
102+ < Field
103+ required
104+ invalid = { ! ! errors . email }
105+ errorText = { errors . email ?. message }
106+ label = "Email"
107+ >
108+ < Input
109+ id = "email"
110+ { ...register ( "email" , {
111+ required : "Email is required" ,
112+ pattern : emailPattern ,
113+ } ) }
114+ placeholder = "Email"
115+ type = "email"
116+ />
117+ </ Field >
118+
119+ < Field
120+ invalid = { ! ! errors . full_name }
121+ errorText = { errors . full_name ?. message }
122+ label = "Full Name"
123+ >
124+ < Input
125+ id = "name"
126+ { ...register ( "full_name" ) }
127+ placeholder = "Full name"
128+ type = "text"
129+ />
130+ </ Field >
131+
132+ < Field
133+ required
134+ invalid = { ! ! errors . password }
135+ errorText = { errors . password ?. message }
136+ label = "Set Password"
137+ >
138+ < Input
139+ id = "password"
140+ { ...register ( "password" , {
141+ required : "Password is required" ,
142+ minLength : {
143+ value : 8 ,
144+ message : "Password must be at least 8 characters" ,
145+ } ,
146+ } ) }
147+ placeholder = "Password"
148+ type = "password"
149+ />
150+ </ Field >
151+
152+ < Field
153+ required
154+ invalid = { ! ! errors . confirm_password }
155+ errorText = { errors . confirm_password ?. message }
156+ label = "Confirm Password"
157+ >
158+ < Input
159+ id = "confirm_password"
160+ { ...register ( "confirm_password" , {
161+ required : "Please confirm your password" ,
162+ validate : ( value ) =>
163+ value === getValues ( ) . password ||
164+ "The passwords do not match" ,
165+ } ) }
166+ placeholder = "Password"
167+ type = "password"
168+ />
169+ </ Field >
170+ </ VStack >
171+
172+ < Flex mt = { 4 } direction = "column" gap = { 4 } >
173+ < Controller
174+ control = { control }
175+ name = "is_superuser"
176+ render = { ( { field } ) => (
177+ < Field disabled = { field . disabled } colorPalette = "teal" >
178+ < Checkbox
179+ checked = { field . value }
180+ onCheckedChange = { ( { checked } ) => field . onChange ( checked ) }
181+ >
182+ Is superuser?
183+ </ Checkbox >
184+ </ Field >
185+ ) }
129186 />
130- { errors . password && (
131- < FormErrorMessage > { errors . password . message } </ FormErrorMessage >
132- ) }
133- </ FormControl >
134- < FormControl
135- mt = { 4 }
136- isRequired
137- isInvalid = { ! ! errors . confirm_password }
138- >
139- < FormLabel htmlFor = "confirm_password" > Confirm Password</ FormLabel >
140- < Input
141- id = "confirm_password"
142- { ...register ( "confirm_password" , {
143- required : "Please confirm your password" ,
144- validate : ( value ) =>
145- value === getValues ( ) . password ||
146- "The passwords do not match" ,
147- } ) }
148- placeholder = "Password"
149- type = "password"
187+ < Controller
188+ control = { control }
189+ name = "is_active"
190+ render = { ( { field } ) => (
191+ < Field disabled = { field . disabled } colorPalette = "teal" >
192+ < Checkbox
193+ checked = { field . value }
194+ onCheckedChange = { ( { checked } ) => field . onChange ( checked ) }
195+ >
196+ Is active?
197+ </ Checkbox >
198+ </ Field >
199+ ) }
150200 />
151- { errors . confirm_password && (
152- < FormErrorMessage >
153- { errors . confirm_password . message }
154- </ FormErrorMessage >
155- ) }
156- </ FormControl >
157- < Flex mt = { 4 } >
158- < FormControl >
159- < Checkbox { ...register ( "is_superuser" ) } colorScheme = "teal" >
160- Is superuser?
161- </ Checkbox >
162- </ FormControl >
163- < FormControl >
164- < Checkbox { ...register ( "is_active" ) } colorScheme = "teal" >
165- Is active?
166- </ Checkbox >
167- </ FormControl >
168201 </ Flex >
169- </ ModalBody >
170- < ModalFooter gap = { 3 } >
171- < Button variant = "primary" type = "submit" isLoading = { isSubmitting } >
202+ </ DialogBody >
203+
204+ < DialogFooter gap = { 2 } >
205+ < DialogActionTrigger asChild >
206+ < Button
207+ variant = "subtle"
208+ colorPalette = "gray"
209+ disabled = { isSubmitting }
210+ >
211+ Cancel
212+ </ Button >
213+ </ DialogActionTrigger >
214+ < Button
215+ variant = "solid"
216+ type = "submit"
217+ disabled = { ! isValid }
218+ loading = { isSubmitting }
219+ >
172220 Save
173221 </ Button >
174- < Button onClick = { onClose } > Cancel </ Button >
175- </ ModalFooter >
176- </ ModalContent >
177- </ Modal >
178- </ >
222+ </ DialogFooter >
223+ </ form >
224+ < DialogCloseTrigger / >
225+ </ DialogContent >
226+ </ DialogRoot >
179227 )
180228}
181229
0 commit comments