Skip to content

Commit

Permalink
feat: react hook form setting and feature add
Browse files Browse the repository at this point in the history
Co-authored-by: Minseok Choi <[email protected]>
  • Loading branch information
minsgy and minsgy committed Jun 10, 2024
1 parent 0b2b91b commit fea5c43
Show file tree
Hide file tree
Showing 10 changed files with 311 additions and 106 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"@codemirror/language": "^6.10.2",
"@codemirror/lint": "^6.8.0",
"@faker-js/faker": "^8.4.1",
"@hookform/resolvers": "^3.6.0",
"@radix-ui/react-accordion": "1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-label": "^2.0.2",
Expand Down Expand Up @@ -70,7 +71,8 @@
"tailwind-merge": "2.3.0",
"tailwindcss-animate": "1.0.7",
"ts-pattern": "^5.1.2",
"typescript": "5.4.5"
"typescript": "5.4.5",
"zod": "^3.23.8"
},
"devDependencies": {
"autoprefixer": "^10.4.19",
Expand Down
20 changes: 20 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

296 changes: 197 additions & 99 deletions src/features/RouteEditPanel/CreateEditForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Button } from "@/shared/ui/button"
import { Input } from "@/shared/ui/input"
import { H4, P } from "@/shared/ui/typography"
import {
Select,
SelectTrigger,
Expand All @@ -14,112 +13,211 @@ import { StatusSelect } from "./StatusSelect"
import babel from "prettier/plugins/babel"
import prettierPluginEstree from "prettier/plugins/estree"
import { Separator } from "@/shared/ui/separator"
import { Controller, useForm } from "react-hook-form"
import { HttpMethods } from "msw"
import { ROUTE_METHODS } from "@/constants"

type CreateEditFormValues = {
delay?: string
description?: string
method: HttpMethods
url: string
status: string
response: string
}
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/shared/ui/form"
import { useCreateEditFormState } from "./hooks/useCreateEditFormState"
import { Plus } from "@/shared/icons"
import { getDefaultResponse } from "./utils/getDefaultResponse"

export const CreateEditForm = () => {
const {
register,
control,
handleSubmit,
setError,
formState: { errors },
} = useForm<CreateEditFormValues>({
defaultValues: {
method: HttpMethods.GET,
url: "",
status: "200",
response: "{}",
},
})
const { routeForm, handleRouteFormSubmit } = useCreateEditFormState()

const handlers = routeForm.watch("handlers")
const selectedHandlerId = routeForm.watch("selectedHandlerId")
const selectedHandlerIndex =
handlers.findIndex((handler) => handler.id === selectedHandlerId) ?? 0

return (
<form
onSubmit={handleSubmit((value) => {
console.log(value)
})}
>
<div className="flex py-[12px] px-[16px]">
<Controller
control={control}
name="method"
render={({ field }) => (
<Select defaultValue={field.value} onValueChange={field.onChange}>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
{ROUTE_METHODS.map((method) => (
<SelectItem key={method} value={method}>
{method}
</SelectItem>
))}
</SelectContent>
</Select>
)}
/>
<Input
placeholder="Route URL https://example.com/..."
{...register("url")}
/>
<Button type="submit">Save</Button>
</div>
<Separator />
<div className="flex py-[12px] px-[16px]">
<StatusSelect defaultValue={"200"} />
<Input placeholder="Description" {...register("description")} />
<Input placeholder="delay" {...register("delay")} />
</div>
<Separator />
<div className="flex justify-between w-full text-left py-[12px] px-[16px]">
<H4>Response Body</H4>
{errors.response && (
<P className="text-red-500">{errors.response.message}</P>
)}
</div>
<div className="py-[12px] px-[16px] text-left">
<Controller
control={control}
name="response"
render={({ field }) => (
<ResponseJsonEditor
value={field.value}
onChange={(value) => {
console.log(value)
field.onChange(value)
}}
onSave={async () => {
try {
const formattedResponse = await format(field.value, {
tabWidth: 2,
printWidth: 100,
parser: "json5",
plugins: [babel, prettierPluginEstree],
})
// LINK: https://github.com/prettier/prettier/issues/6360
field.onChange(formattedResponse.replace(/[\r\n]+$/, ""))
} catch (error) {
const formattedError =
error instanceof Error ? error.message : "Unknown Error"
setError("response", {
message: formattedError,
})
}
<div className="overflow-y-auto scrollbar-hide">
<Form {...routeForm}>
<form
onSubmit={routeForm.handleSubmit(handleRouteFormSubmit)}
className="text-left"
>
<div className="flex py-[12px] px-[16px] space-x-2 items-end">
<FormField
control={routeForm.control}
name="method"
render={({ field }) => (
<FormItem>
<FormLabel>Methods</FormLabel>
<FormControl>
<Select
defaultValue={field.value}
onValueChange={field.onChange}
>
<SelectTrigger className="w-[180px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
{ROUTE_METHODS.map((method) => (
<SelectItem key={method} value={method}>
{method}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={routeForm.control}
name="url"
render={({ field }) => (
<FormItem className="w-full">
<FormLabel>URL</FormLabel>
<FormControl>
<Input placeholder="https://example.com/..." {...field} />
</FormControl>
<FormMessage className="text-red-400" />
</FormItem>
)}
/>
<FormField
control={routeForm.control}
name="delay"
render={({ field }) => (
<FormItem>
<FormLabel>Delay(ms)</FormLabel>
<FormControl>
<Input type="number" {...field} />
</FormControl>
<FormMessage className="text-red-400" />
</FormItem>
)}
/>
<Button type="submit">Save</Button>
</div>
<Separator />
<div className="flex py-[12px] px-[16px] space-x-2 text-left">
<Button
type="button"
variant="outline"
onClick={() => {
routeForm.setValue("handlers", [
...handlers,
getDefaultResponse(handlers.length),
])
}}
>
<Plus />
</Button>
<FormField
control={routeForm.control}
name="selectedHandlerId"
render={({ field }) => (
<FormItem className="flex-1">
<FormControl>
<Select
onValueChange={field.onChange}
defaultValue={handlers[0].id}
>
<SelectTrigger
className="flex-1"
placeholder="Select a handler"
>
<SelectValue />
</SelectTrigger>
<SelectContent>
{handlers.map(({ status, description, id }) => (
<SelectItem key={id} value={id}>
{status} - {description}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
<FormMessage className="text-red-400" />
</FormItem>
)}
/>
</div>
</form>
<Separator />
<div className="flex py-[12px] px-[16px] space-x-2 text-left">
<FormField
control={routeForm.control}
name={`handlers.${selectedHandlerIndex}.status`}
render={({ field }) => {
console.log(field.value, selectedHandlerIndex)
return (
<FormItem>
<FormLabel>Response Status</FormLabel>
<StatusSelect
onValueChange={field.onChange}
defaultValue={String(field.value)}
/>
</FormItem>
)
}}
/>
<FormField
control={routeForm.control}
name={`handlers.${selectedHandlerIndex}.description`}
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>Description</FormLabel>
<FormControl>
<Input placeholder="ex) userinfo get" {...field} />
</FormControl>
<FormMessage className="text-red-400" />
</FormItem>
)}
/>
</div>
<Separator />
<FormField
control={routeForm.control}
name={`handlers.${selectedHandlerIndex}.response`}
render={({ field }) => (
<FormItem className="py-[12px] px-[16px] text-left">
<div className="flex justify-between w-full text-left py-[12px]">
<FormLabel>Response Body</FormLabel>
<FormMessage className="text-red-400" />
</div>
<FormControl>
<ResponseJsonEditor
value={field.value}
onChange={(value) => {
console.log(value)
field.onChange(value)
}}
onSave={async () => {
try {
const formattedResponse = await format(field.value, {
tabWidth: 2,
printWidth: 100,
parser: "json5",
plugins: [babel, prettierPluginEstree],
})
// LINK: https://github.com/prettier/prettier/issues/6360
field.onChange(formattedResponse.replace(/[\r\n]+$/, ""))
} catch (error) {
const formattedError =
error instanceof Error ? error.message : "Unknown Error"
routeForm.setError(
`handlers.${selectedHandlerIndex}.response`,
{
message: formattedError,
}
)
}
}}
/>
</FormControl>
</FormItem>
)}
/>
</div>
</form>
</Form>
</div>
)
}
Loading

0 comments on commit fea5c43

Please sign in to comment.