diff options
Diffstat (limited to 'lib/integration/table/integration-edit-sheet.tsx')
| -rw-r--r-- | lib/integration/table/integration-edit-sheet.tsx | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/lib/integration/table/integration-edit-sheet.tsx b/lib/integration/table/integration-edit-sheet.tsx new file mode 100644 index 00000000..553a7870 --- /dev/null +++ b/lib/integration/table/integration-edit-sheet.tsx @@ -0,0 +1,278 @@ +"use client" + +import * as React from "react" +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import { toast } from "sonner" +import * as z from "zod" +import { Loader2 } from "lucide-react" + +import { Button } from "@/components/ui/button" +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, +} from "@/components/ui/sheet" +import { Input } from "@/components/ui/input" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Textarea } from "@/components/ui/textarea" +import { updateIntegration } from "../service" +import { integrations } from "@/db/schema/integration" + +const updateIntegrationSchema = z.object({ + code: z.string().min(1, "코드는 필수입니다."), + name: z.string().min(1, "이름은 필수입니다."), + type: z.enum(["rest_api", "soap", "db_to_db"], { required_error: "타입은 필수입니다." }), + description: z.string().optional(), + sourceSystem: z.string().min(1, "소스 시스템은 필수입니다."), + targetSystem: z.string().min(1, "타겟 시스템은 필수입니다."), + status: z.enum(["active", "inactive", "deprecated"]), + metadata: z.any().optional(), +}) + +type UpdateIntegrationFormValues = z.infer<typeof updateIntegrationSchema> + +interface IntegrationEditSheetProps { + data: typeof integrations.$inferSelect | null + open?: boolean + onOpenChange?: (open: boolean) => void + onSuccess?: () => void +} + +export function IntegrationEditSheet({ data, open, onOpenChange, onSuccess }: IntegrationEditSheetProps) { + const [isLoading, setIsLoading] = React.useState(false) + + const form = useForm<UpdateIntegrationFormValues>({ + resolver: zodResolver(updateIntegrationSchema), + defaultValues: { + code: data?.code || "", + name: data?.name || "", + type: data?.type || "rest_api", + description: data?.description || "", + sourceSystem: data?.sourceSystem || "", + targetSystem: data?.targetSystem || "", + status: data?.status || "active", + metadata: data?.metadata || {}, + }, + }) + + React.useEffect(() => { + if (data) { + form.reset({ + code: data.code || "", + name: data.name || "", + type: data.type || "rest_api", + description: data.description || "", + sourceSystem: data.sourceSystem || "", + targetSystem: data.targetSystem || "", + status: data.status || "active", + metadata: data.metadata || {}, + }) + } + }, [data, form]) + + const handleCancel = () => { + form.reset() + onOpenChange?.(false) + } + + const onSubmit = async (formData: UpdateIntegrationFormValues) => { + if (!data) return + + setIsLoading(true) + try { + const result = await updateIntegration(data.id, formData) + if (result.data) { + toast.success("인터페이스가 성공적으로 수정되었습니다.") + form.reset() + onOpenChange?.(false) + if (onSuccess) { + onSuccess() + } + } else { + toast.error(result.error || "수정 중 오류가 발생했습니다.") + } + } catch (error) { + console.error("인터페이스 수정 오류:", error) + toast.error("인터페이스 수정에 실패했습니다.") + } finally { + setIsLoading(false) + } + } + + return ( + <Sheet open={open} onOpenChange={onOpenChange}> + <SheetContent className="w-[400px] sm:w-[540px]"> + <SheetHeader> + <SheetTitle>인터페이스 수정</SheetTitle> + <SheetDescription> + 인터페이스 정보를 수정합니다. 필수 정보를 입력해주세요. + <span className="text-red-500 mt-1 block text-sm">* 표시된 항목은 필수 입력사항입니다.</span> + </SheetDescription> + </SheetHeader> + + <Form {...form}> + <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4 mt-6"> + <FormField + control={form.control} + name="code" + render={({ field }) => ( + <FormItem> + <FormLabel> + 코드 <span className="text-red-500">*</span> + </FormLabel> + <FormControl> + <Input placeholder="INT_OPS_001" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="name" + render={({ field }) => ( + <FormItem> + <FormLabel> + 이름 <span className="text-red-500">*</span> + </FormLabel> + <FormControl> + <Input placeholder="인터페이스 이름" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="type" + render={({ field }) => ( + <FormItem> + <FormLabel> + 타입 <span className="text-red-500">*</span> + </FormLabel> + <Select onValueChange={field.onChange} defaultValue={field.value}> + <FormControl> + <SelectTrigger> + <SelectValue placeholder="타입 선택" /> + </SelectTrigger> + </FormControl> + <SelectContent> + <SelectItem value="rest_api">REST API</SelectItem> + <SelectItem value="soap">SOAP</SelectItem> + <SelectItem value="db_to_db">DB to DB</SelectItem> + </SelectContent> + </Select> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="sourceSystem" + render={({ field }) => ( + <FormItem> + <FormLabel> + 소스 시스템 <span className="text-red-500">*</span> + </FormLabel> + <FormControl> + <Input placeholder="ERP, WMS 등" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="targetSystem" + render={({ field }) => ( + <FormItem> + <FormLabel> + 타겟 시스템 <span className="text-red-500">*</span> + </FormLabel> + <FormControl> + <Input placeholder="ERP, WMS 등" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="status" + render={({ field }) => ( + <FormItem> + <FormLabel> + 상태 <span className="text-red-500">*</span> + </FormLabel> + <Select onValueChange={field.onChange} defaultValue={field.value}> + <FormControl> + <SelectTrigger> + <SelectValue placeholder="상태 선택" /> + </SelectTrigger> + </FormControl> + <SelectContent> + <SelectItem value="active">활성</SelectItem> + <SelectItem value="inactive">비활성</SelectItem> + <SelectItem value="deprecated">사용중단</SelectItem> + </SelectContent> + </Select> + <FormMessage /> + </FormItem> + )} + /> + + <FormField + control={form.control} + name="description" + render={({ field }) => ( + <FormItem> + <FormLabel>설명</FormLabel> + <FormControl> + <Textarea placeholder="인터페이스에 대한 설명" {...field} /> + </FormControl> + <FormMessage /> + </FormItem> + )} + /> + </form> + </Form> + + <SheetFooter className="mt-6"> + <Button + type="button" + variant="outline" + onClick={handleCancel} + disabled={isLoading} + > + 취소 + </Button> + <Button + type="submit" + onClick={form.handleSubmit(onSubmit)} + disabled={isLoading} + > + {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} + {isLoading ? "수정 중..." : "수정"} + </Button> + </SheetFooter> + </SheetContent> + </Sheet> + ) +}
\ No newline at end of file |
