Skip to content

Commit 55df823

Browse files
alejsdevgithub-actions
and
github-actions
authored
🛂 Migrate to Chakra UI v3 (#1496)
Co-authored-by: github-actions <github-actions@github.com>
1 parent 74e2604 commit 55df823

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+6712
-6429
lines changed

frontend/openapi-ts.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default defineConfig({
1515
// @ts-ignore
1616
let name: string = operation.name
1717
// @ts-ignore
18-
let service: string = operation.service
18+
const service: string = operation.service
1919

2020
if (service && name.toLowerCase().startsWith(service.toLowerCase())) {
2121
name = name.slice(service.length)

frontend/package-lock.json

+3,970-4,823
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,19 @@
1111
"generate-client": "openapi-ts"
1212
},
1313
"dependencies": {
14-
"@chakra-ui/icons": "2.1.1",
15-
"@chakra-ui/react": "2.8.2",
16-
"@emotion/react": "11.11.3",
17-
"@emotion/styled": "11.11.0",
14+
"@chakra-ui/react": "^3.8.0",
15+
"@emotion/react": "^11.14.0",
1816
"@tanstack/react-query": "^5.28.14",
1917
"@tanstack/react-query-devtools": "^5.28.14",
2018
"@tanstack/react-router": "1.19.1",
2119
"axios": "1.7.4",
2220
"form-data": "4.0.0",
23-
"framer-motion": "10.16.16",
21+
"next-themes": "^0.4.4",
2422
"react": "^18.2.0",
2523
"react-dom": "^18.2.0",
2624
"react-error-boundary": "^4.0.13",
2725
"react-hook-form": "7.49.3",
28-
"react-icons": "5.0.1"
26+
"react-icons": "^5.4.0"
2927
},
3028
"devDependencies": {
3129
"@biomejs/biome": "1.6.1",

frontend/src/components/Admin/AddUser.tsx

+170-122
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,48 @@
1+
import { useMutation, useQueryClient } from "@tanstack/react-query"
2+
import { Controller, type SubmitHandler, useForm } from "react-hook-form"
3+
14
import {
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"
2015
import { type UserCreate, UsersService } from "../../client"
2116
import type { ApiError } from "../../client/core/ApiError"
2217
import useCustomToast from "../../hooks/useCustomToast"
2318
import { 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

3031
interface 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

Comments
 (0)