Skip to content

Commit

Permalink
feat: editor feature add and handler add feature
Browse files Browse the repository at this point in the history
  • Loading branch information
minsgy committed Jun 11, 2024
1 parent 8e4c120 commit e19c0d8
Show file tree
Hide file tree
Showing 14 changed files with 317 additions and 160 deletions.
107 changes: 63 additions & 44 deletions src/features/DevtoolsHandlerList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { match } from "ts-pattern"

import { cn } from "@/shared/lib/cn"
import { InlineCode, P } from "@/shared/ui/typography"
import { InlineCode } from "@/shared/ui/typography"
import { HttpMethods } from "msw"
import {
useEditorRouteState,
Expand All @@ -13,59 +13,78 @@ import {
import { HandlerSelect } from "./HandlerSelect"
import { Button } from "@/shared/ui/button"
import { Switch } from "@/shared/ui/switch"
import {
TableCaption,
TableHeader,
TableRow,
TableHead,
TableBody,
TableCell,
Table,
} from "@/shared/ui/table"
import { Edit } from "@/shared/icons"

export const DevtoolsHandlerList = () => {
const isEnabled = useIsEnabledValue()
const { routes, onToggleHandler, onSelectHandler } = useRoute()
const { onOpenEditPanel } = useEditorRouteState()

return (
<ul className="list-none overflow-y-auto h-full scrollbar-hide rounded-[4px] bg-card">
<li className="flex items-center max-[600px]:hidden text-gray-300 sticky top-0 z-10 h-[44px] bg-card">
<P className="font-semibold w-[80px] shrink-0">METHODS</P>
<P className="font-semibold pl-[12px] flex-1 text-left">URL</P>
<P className="font-semibold flex-1 text-left">OPTIONS</P>
</li>
{routes.map((route) => (
<li key={route.id} className="py-[12px] flex items-center">
<div className="flex items-center w-full max-[600px]:flex-col max-[600px]:items-stretch">
<div className="flex items-center flex-1">
<Table>
<TableCaption>A list of your recent invoices.</TableCaption>
<TableHeader>
<TableRow>
<TableHead className="w-[100px]">Methods</TableHead>
<TableHead>URL</TableHead>
<TableHead>Options</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{routes.map((route) => (
<TableRow key={route.id} className="py-[16px]">
<TableCell>
<MethodTag method={route.method} />
</TableCell>
<TableCell>
<span className="flex-1 pl-[12px] font-semibold text-left break-word inline-block">
{route.url}
</span>
</div>
<div className="flex items-center max-[600px]:pt-[12px]">
{route.origin === "custom" && (
<InlineCode className="mr-[12px]">{route.origin}</InlineCode>
)}
<HandlerSelect
onValueChange={(handlerId) =>
onSelectHandler(route.id, handlerId)
}
options={route.handlers ?? []}
defaultValue={route.handlers?.[0]?.id ?? undefined}
/>
<Button
className="ml-[12px]"
variant="ghost"
onClick={() => {
onOpenEditPanel(route)
}}>
Edit
</Button>
<Switch
disabled={!isEnabled}
checked={route.enabled}
onCheckedChange={(checked) => {
onToggleHandler(route.id, checked)
}}
/>
</div>
</div>
</li>
))}
</ul>
</TableCell>
<TableCell>
<div className="flex items-center">
<HandlerSelect
onValueChange={(handlerId) =>
onSelectHandler(route.id, handlerId)
}
options={route.handlers}
defaultValue={route.handlers?.[0]?.id ?? undefined}
/>
{route.origin === "custom" && (
<InlineCode>{route.origin}</InlineCode>
)}
<div className="flex space-x-2 ml-auto items-center">
<Button
className="ml-[12px]"
variant="ghost"
onClick={() => {
onOpenEditPanel(route)
}}>
<Edit />
</Button>
<Switch
disabled={!isEnabled}
checked={route.enabled}
onCheckedChange={(checked) => {
onToggleHandler(route.id, checked)
}}
/>
</div>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}

Expand All @@ -79,7 +98,7 @@ export const MethodTag = ({ method }: { method: HttpMethods }) => {
.otherwise(() => "bg-black")

return (
<div className="inline-flex justify-center basis-[80px] shrink-0">
<div className="inline-flex justify-center w-full shrink-0">
<InlineCode className={cn("text-white w-full", className)}>
{method}
</InlineCode>
Expand Down
13 changes: 4 additions & 9 deletions src/features/RouteEditPanel/CreateEditForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,28 @@ import { Form } from "@/shared/ui/form"
import { useCreateEditFormState } from "./hooks/useCreateEditFormState"
import { EditHandlerForm } from "./EditHandlerForm"
import { EditRouteForm } from "./EditRouteForm"
import { EnhancedDevtoolsRoute } from "@/types"

type CreateEditFormProps = {
selectedRoute: EnhancedDevtoolsRoute | null
}

export const CreateEditForm = ({ selectedRoute }: CreateEditFormProps) => {
export const CreateEditForm = () => {
const {
routeForm,
handleRouteFormSubmit,
handlerForm,
handleHandlerFormSubmit,
} = useCreateEditFormState(selectedRoute)
} = useCreateEditFormState()

return (
<div className="overflow-y-auto scrollbar-hide">
<Form {...routeForm}>
<form
onSubmit={routeForm.handleSubmit(handleRouteFormSubmit)}
className="text-left">
<EditRouteForm routeForm={routeForm} />
<EditRouteForm />
</form>
</Form>
<Separator />
<Form {...handlerForm}>
<form onSubmit={handlerForm.handleSubmit(handleHandlerFormSubmit)}>
<EditHandlerForm handlerForm={handlerForm} />
<EditHandlerForm />
</form>
</Form>
</div>
Expand Down
22 changes: 9 additions & 13 deletions src/features/RouteEditPanel/EditHandlerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ import {
} from "@/shared/ui/form"
import { StatusSelect } from "./StatusSelect"
import { ResponseJsonEditor } from "./ResponseJsonEditor"
import { UseFormReturn } from "react-hook-form"
import { useFormContext } from "react-hook-form"
import { CreateHandlerFormValues } from "./hooks/useCreateEditFormState"
import { Input } from "@/shared/ui/input"
import { Separator } from "@/shared/ui/separator"
import { Button } from "@/shared/ui/button"
import { formattedJson } from "./utils/formattedJson"

type EditHandlerFormProps = {
handlerForm: UseFormReturn<CreateHandlerFormValues>
}
export const EditHandlerForm = () => {
const handlerForm = useFormContext<CreateHandlerFormValues>()

export const EditHandlerForm = ({ handlerForm }: EditHandlerFormProps) => {
return (
<>
<div className="flex py-[12px] px-[16px] space-x-2 text-left items-end">
Expand All @@ -29,12 +27,11 @@ export const EditHandlerForm = ({ handlerForm }: EditHandlerFormProps) => {
return (
<FormItem>
<FormLabel>Response Status</FormLabel>
<FormControl>
<StatusSelect
onValueChange={field.onChange}
defaultValue={String(field.value)}
/>
</FormControl>
<StatusSelect
value={String(field.value)}
onValueChange={field.onChange}
defaultValue={String(field.value)}
/>
<FormMessage />
</FormItem>
)
Expand Down Expand Up @@ -74,8 +71,7 @@ export const EditHandlerForm = ({ handlerForm }: EditHandlerFormProps) => {
onSave={async () => {
try {
const formattedResponse = await formattedJson(field.value)
// LINK: https://github.com/prettier/prettier/issues/6360
field.onChange(formattedResponse.replace(/[\r\n]+$/, ""))
field.onChange(formattedResponse)
} catch (error) {
const formattedError =
error instanceof Error ? error.message : "Unknown Error"
Expand Down
106 changes: 52 additions & 54 deletions src/features/RouteEditPanel/EditRouteForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,28 +17,32 @@ import {
SelectValue,
} from "@/shared/ui/select"
import { Separator } from "@/shared/ui/separator"
import { UseFormReturn } from "react-hook-form"
import { useFormContext } from "react-hook-form"
import { CreateRouteFormValues } from "./hooks/useCreateEditFormState"
import { getDefaultResponse } from "./utils/getDefaultResponse"
import { useEffect, useState } from "react"
import { match } from "ts-pattern"

type EditRouteFormProps = {
routeForm: UseFormReturn<CreateRouteFormValues>
}

export const EditRouteForm = ({ routeForm }: EditRouteFormProps) => {
export const EditRouteForm = () => {
const [selectedHandlerId, setSelectedHandlerId] = useState("")
const routeForm = useFormContext<CreateRouteFormValues>()
const handlers = routeForm.watch("handlers")
const handleAddHandler = () => {
const defaultHandler = getDefaultResponse(handlers.length)
routeForm.setValue(
"handlers",
[...handlers, getDefaultResponse(handlers.length)],
{
shouldValidate: true,
}
)
routeForm.setValue("selectedHandlerId", defaultHandler.id)
routeForm.setValue("handlers", [...handlers, defaultHandler])
}

useEffect(() => {
if (handlers.length === 0) return
const selectedHandlerId = match(handlers.length)
.with(1, () => handlers[0]?.id)
.otherwise(() => handlers[handlers.length - 1]?.id)
setSelectedHandlerId(selectedHandlerId)
routeForm.setValue("temporarySelectedHandlerId", selectedHandlerId, {
shouldValidate: true,
})
}, [handlers, setSelectedHandlerId])

return (
<>
<div className="flex py-[12px] px-[16px] space-x-2 items-end">
Expand All @@ -48,22 +52,23 @@ export const EditRouteForm = ({ routeForm }: EditRouteFormProps) => {
render={({ field }) => (
<FormItem>
<FormLabel>Methods</FormLabel>
<FormControl>
<Select
defaultValue={field.value}
onValueChange={field.onChange}>
<Select
defaultValue={field.value}
onValueChange={field.onChange}
value={field.value}>
<FormControl>
<SelectTrigger className="min-w-[60px]">
<SelectValue />
</SelectTrigger>
<SelectContent>
{ROUTE_METHODS.map((method) => (
<SelectItem key={method} value={method}>
{method}
</SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
</FormControl>
<SelectContent>
{ROUTE_METHODS.map((method) => (
<SelectItem key={method} value={method}>
{method}
</SelectItem>
))}
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
Expand Down Expand Up @@ -101,33 +106,26 @@ export const EditRouteForm = ({ routeForm }: EditRouteFormProps) => {
<Button type="button" variant="outline" onClick={handleAddHandler}>
<Plus />
</Button>
<FormField
control={routeForm.control}
name="selectedHandlerId"
render={({ field }) => (
<FormItem className="flex-1">
<FormControl>
<Select
onValueChange={field.onChange}
defaultValue={field.value}>
<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>
)}
/>
<FormItem className="flex-1">
<Select
onValueChange={(value) => {
routeForm.setValue("temporarySelectedHandlerId", value)
setSelectedHandlerId(value)
}}
value={selectedHandlerId}
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>
</FormItem>
</div>
</>
)
Expand Down
Loading

0 comments on commit e19c0d8

Please sign in to comment.