From 7305a614ca20d50e6ab50bbcfbb128a6f1f90e53 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Sun, 15 Jun 2025 04:41:55 +0000
Subject: (최겸) 기술영업 벤더 개발
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/tech-vendors/table/add-vendor-dialog.tsx | 458 +++++++++++++++++++++++++++
 1 file changed, 458 insertions(+)
 create mode 100644 lib/tech-vendors/table/add-vendor-dialog.tsx

(limited to 'lib/tech-vendors/table/add-vendor-dialog.tsx')

diff --git a/lib/tech-vendors/table/add-vendor-dialog.tsx b/lib/tech-vendors/table/add-vendor-dialog.tsx
new file mode 100644
index 00000000..bc260d51
--- /dev/null
+++ b/lib/tech-vendors/table/add-vendor-dialog.tsx
@@ -0,0 +1,458 @@
+"use client"
+
+import * as React from "react"
+import { zodResolver } from "@hookform/resolvers/zod"
+import { useForm } from "react-hook-form"
+import { toast } from "sonner"
+import { z } from "zod"
+
+import { Button } from "@/components/ui/button"
+import {
+  Dialog,
+  DialogContent,
+  DialogDescription,
+  DialogFooter,
+  DialogHeader,
+  DialogTitle,
+  DialogTrigger,
+} from "@/components/ui/dialog"
+import {
+  Form,
+  FormControl,
+  FormField,
+  FormItem,
+  FormLabel,
+  FormMessage,
+} from "@/components/ui/form"
+import { Input } from "@/components/ui/input"
+import {
+  Select,
+  SelectContent,
+  SelectItem,
+  SelectTrigger,
+  SelectValue,
+} from "@/components/ui/select"
+import { Textarea } from "@/components/ui/textarea"
+import { Plus, Loader2 } from "lucide-react"
+
+import { addTechVendor } from "../service"
+
+// 폼 스키마 정의
+const addVendorSchema = z.object({
+  vendorName: z.string().min(1, "업체명을 입력해주세요"),
+  vendorCode: z.string().optional(),
+  email: z.string().email("올바른 이메일 주소를 입력해주세요"),
+  taxId: z.string().optional(),
+  country: z.string().optional(),
+  countryEng: z.string().optional(),
+  countryFab: z.string().optional(),
+  agentName: z.string().optional(),
+  agentPhone: z.string().optional(),
+  agentEmail: z.string().email("올바른 이메일 주소를 입력해주세요").optional().or(z.literal("")),
+  address: z.string().optional(),
+  phone: z.string().optional(),
+  website: z.string().optional(),
+  techVendorType: z.enum(["조선", "해양TOP", "해양HULL"], {
+    required_error: "벤더 타입을 선택해주세요",
+  }),
+  representativeName: z.string().optional(),
+  representativeEmail: z.string().email("올바른 이메일 주소를 입력해주세요").optional().or(z.literal("")),
+  representativePhone: z.string().optional(),
+  representativeBirth: z.string().optional(),
+})
+
+type AddVendorFormData = z.infer<typeof addVendorSchema>
+
+interface AddVendorDialogProps {
+  onSuccess?: () => void
+}
+
+export function AddVendorDialog({ onSuccess }: AddVendorDialogProps) {
+  const [open, setOpen] = React.useState(false)
+  const [isLoading, setIsLoading] = React.useState(false)
+
+  const form = useForm<AddVendorFormData>({
+    resolver: zodResolver(addVendorSchema),
+    defaultValues: {
+      vendorName: "",
+      vendorCode: "",
+      email: "",
+      taxId: "",
+      country: "",
+      countryEng: "",
+      countryFab: "",
+      agentName: "",
+      agentPhone: "",
+      agentEmail: "",
+      address: "",
+      phone: "",
+      website: "",
+      techVendorType: undefined,
+      representativeName: "",
+      representativeEmail: "",
+      representativePhone: "",
+      representativeBirth: "",
+    },
+  })
+
+  const onSubmit = async (data: AddVendorFormData) => {
+    setIsLoading(true)
+    try {
+      const result = await addTechVendor({
+        ...data,
+        vendorCode: data.vendorCode || null,
+        country: data.country || null,
+        countryEng: data.countryEng || null,
+        countryFab: data.countryFab || null,
+        agentName: data.agentName || null,
+        agentPhone: data.agentPhone || null,
+        agentEmail: data.agentEmail || null,
+        address: data.address || null,
+        phone: data.phone || null,
+        website: data.website || null,
+        representativeName: data.representativeName || null,
+        representativeEmail: data.representativeEmail || null,
+        representativePhone: data.representativePhone || null,
+        representativeBirth: data.representativeBirth || null,
+        taxId: data.taxId || "",
+      })
+
+      if (result.success) {
+        toast.success("벤더가 성공적으로 추가되었습니다.")
+        form.reset()
+        setOpen(false)
+        onSuccess?.()
+      } else {
+        toast.error(result.error || "벤더 추가 중 오류가 발생했습니다.")
+      }
+    } catch (error) {
+      console.error("벤더 추가 오류:", error)
+      toast.error("벤더 추가 중 오류가 발생했습니다.")
+    } finally {
+      setIsLoading(false)
+    }
+  }
+
+  return (
+    <Dialog open={open} onOpenChange={setOpen}>
+      <DialogTrigger asChild>
+        <Button size="sm" className="gap-2">
+          <Plus className="size-4" />
+          벤더 추가
+        </Button>
+      </DialogTrigger>
+      <DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
+        <DialogHeader>
+          <DialogTitle>새 기술영업 벤더 추가</DialogTitle>
+          <DialogDescription>
+            새로운 기술영업 벤더 정보를 입력하고 사용자 계정을 생성합니다.
+          </DialogDescription>
+        </DialogHeader>
+
+        <Form {...form}>
+          <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
+            {/* 기본 정보 */}
+            <div className="space-y-4">
+              <h3 className="text-lg font-medium">기본 정보</h3>
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="vendorName"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>업체명 *</FormLabel>
+                      <FormControl>
+                        <Input placeholder="업체명을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="vendorCode"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>업체 코드</FormLabel>
+                      <FormControl>
+                        <Input placeholder="업체 코드를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="email"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>이메일 *</FormLabel>
+                      <FormControl>
+                        <Input type="email" placeholder="이메일을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="taxId"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>사업자등록번호</FormLabel>
+                      <FormControl>
+                        <Input placeholder="사업자등록번호를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              <FormField
+                control={form.control}
+                name="techVendorType"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>벤더 타입 *</FormLabel>
+                    <Select onValueChange={field.onChange} defaultValue={field.value}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="벤더 타입을 선택하세요" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        <SelectItem value="조선">조선</SelectItem>
+                        <SelectItem value="해양TOP">해양TOP</SelectItem>
+                        <SelectItem value="해양HULL">해양HULL</SelectItem>
+                      </SelectContent>
+                    </Select>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+
+            {/* 연락처 정보 */}
+            <div className="space-y-4">
+              <h3 className="text-lg font-medium">연락처 정보</h3>
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="phone"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>전화번호</FormLabel>
+                      <FormControl>
+                        <Input placeholder="전화번호를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="website"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>웹사이트</FormLabel>
+                      <FormControl>
+                        <Input placeholder="웹사이트 URL을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+
+              <FormField
+                control={form.control}
+                name="address"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>주소</FormLabel>
+                    <FormControl>
+                      <Textarea placeholder="주소를 입력하세요" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+
+            {/* 국가 정보 */}
+            <div className="space-y-4">
+              <h3 className="text-lg font-medium">국가 정보</h3>
+              <div className="grid grid-cols-3 gap-4">
+                <FormField
+                  control={form.control}
+                  name="country"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>국가</FormLabel>
+                      <FormControl>
+                        <Input placeholder="국가를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="countryEng"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>국가 (영문)</FormLabel>
+                      <FormControl>
+                        <Input placeholder="국가 영문명을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="countryFab"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>제조국가</FormLabel>
+                      <FormControl>
+                        <Input placeholder="제조국가를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+            </div>
+
+            {/* 담당자 정보 */}
+            <div className="space-y-4">
+              <h3 className="text-lg font-medium">담당자 정보</h3>
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="agentName"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>담당자명</FormLabel>
+                      <FormControl>
+                        <Input placeholder="담당자명을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="agentPhone"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>담당자 전화번호</FormLabel>
+                      <FormControl>
+                        <Input placeholder="담당자 전화번호를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+              <FormField
+                control={form.control}
+                name="agentEmail"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>담당자 이메일</FormLabel>
+                    <FormControl>
+                      <Input type="email" placeholder="담당자 이메일을 입력하세요" {...field} />
+                    </FormControl>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+            </div>
+
+            {/* 대표자 정보 */}
+            <div className="space-y-4">
+              <h3 className="text-lg font-medium">대표자 정보</h3>
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="representativeName"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>대표자명</FormLabel>
+                      <FormControl>
+                        <Input placeholder="대표자명을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="representativePhone"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>대표자 전화번호</FormLabel>
+                      <FormControl>
+                        <Input placeholder="대표자 전화번호를 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+              <div className="grid grid-cols-2 gap-4">
+                <FormField
+                  control={form.control}
+                  name="representativeEmail"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>대표자 이메일</FormLabel>
+                      <FormControl>
+                        <Input type="email" placeholder="대표자 이메일을 입력하세요" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+                <FormField
+                  control={form.control}
+                  name="representativeBirth"
+                  render={({ field }) => (
+                    <FormItem>
+                      <FormLabel>대표자 생년월일</FormLabel>
+                      <FormControl>
+                        <Input placeholder="YYYY-MM-DD" {...field} />
+                      </FormControl>
+                      <FormMessage />
+                    </FormItem>
+                  )}
+                />
+              </div>
+            </div>
+
+            <DialogFooter>
+              <Button
+                type="button"
+                variant="outline"
+                onClick={() => setOpen(false)}
+                disabled={isLoading}
+              >
+                취소
+              </Button>
+              <Button type="submit" disabled={isLoading}>
+                {isLoading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
+                벤더 추가
+              </Button>
+            </DialogFooter>
+          </form>
+        </Form>
+      </DialogContent>
+    </Dialog>
+  )
+} 
\ No newline at end of file
-- 
cgit v1.2.3

