From ba8cd44a0ed2c613a5f2cee06bfc9bd0f61f21c7 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Fri, 7 Nov 2025 08:39:04 +0000
Subject: (최겸) 입찰/견적 수정사항
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../main/create-general-contract-dialog.tsx        | 156 +++++++++++++--------
 1 file changed, 99 insertions(+), 57 deletions(-)

(limited to 'lib/general-contracts/main/create-general-contract-dialog.tsx')

diff --git a/lib/general-contracts/main/create-general-contract-dialog.tsx b/lib/general-contracts/main/create-general-contract-dialog.tsx
index 2c3fc8bc..168b8cbc 100644
--- a/lib/general-contracts/main/create-general-contract-dialog.tsx
+++ b/lib/general-contracts/main/create-general-contract-dialog.tsx
@@ -20,11 +20,12 @@ import { Textarea } from "@/components/ui/textarea"
 import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
 import { Calendar } from "@/components/ui/calendar"
 import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
-import { CalendarIcon } from "lucide-react"
+import { CalendarIcon, Check, ChevronsUpDown } from "lucide-react"
+import { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem } from "@/components/ui/command"
 import { format } from "date-fns"
 import { ko } from "date-fns/locale"
 import { cn } from "@/lib/utils"
-import { createContract, getVendors, getProjects } from "@/lib/general-contracts/service"
+import { createContract, getVendors } from "@/lib/general-contracts/service"
 import { 
   GENERAL_CONTRACT_CATEGORIES, 
   GENERAL_CONTRACT_TYPES,
@@ -39,7 +40,6 @@ interface CreateContractForm {
   type: string
   executionMethod: string
   vendorId: number | null
-  projectId: number | null
   startDate: Date | undefined
   endDate: Date | undefined
   validityEndDate: Date | undefined
@@ -52,7 +52,8 @@ export function CreateGeneralContractDialog() {
   const [open, setOpen] = React.useState(false)
   const [isLoading, setIsLoading] = React.useState(false)
   const [vendors, setVendors] = React.useState<Array<{ id: number; vendorName: string; vendorCode: string | null }>>([])
-  const [projects, setProjects] = React.useState<Array<{ id: number; code: string; name: string; type: string }>>([])
+  const [vendorSearchTerm, setVendorSearchTerm] = React.useState("")
+  const [vendorOpen, setVendorOpen] = React.useState(false)
 
   const [form, setForm] = React.useState<CreateContractForm>({
     contractNumber: '',
@@ -61,7 +62,6 @@ export function CreateGeneralContractDialog() {
     type: '',
     executionMethod: '',
     vendorId: null,
-    projectId: null,
     startDate: undefined,
     endDate: undefined,
     validityEndDate: undefined,
@@ -70,36 +70,54 @@ export function CreateGeneralContractDialog() {
 
   // 업체 목록 조회
   React.useEffect(() => {
-    const fetchVendors = async () => {
+    const fetchData = async () => {
       try {
         const vendorList = await getVendors()
+        console.log('vendorList', vendorList)
         setVendors(vendorList)
       } catch (error) {
-        console.error('Error fetching vendors:', error)
+        console.error('데이터 조회 오류:', error)
+        toast.error('데이터를 불러오는데 실패했습니다')
+        setVendors([])
       }
     }
-    fetchVendors()
+    fetchData()
   }, [])
 
-  // 프로젝트 목록 조회
-  React.useEffect(() => {
-    const fetchProjects = async () => {
-      try {
-        const projectList = await getProjects()
-        console.log(projectList)
-        setProjects(projectList)
-      } catch (error) {
-        console.error('Error fetching projects:', error)
-      }
-    }
-    fetchProjects()
-  }, [])
+  // 협력업체 검색 필터링
+  const filteredVendors = React.useMemo(() => {
+    if (!vendorSearchTerm.trim()) return vendors
+    const lowerSearch = vendorSearchTerm.toLowerCase()
+    return vendors.filter(
+      vendor => 
+        vendor.vendorName.toLowerCase().includes(lowerSearch) || 
+        (vendor.vendorCode && vendor.vendorCode.toLowerCase().includes(lowerSearch))
+    )
+  }, [vendors, vendorSearchTerm])
 
   const handleSubmit = async () => {
     // 필수 필드 검증
-    if (!form.name || !form.category || !form.type || !form.executionMethod || 
-        !form.vendorId || !form.startDate || !form.endDate) {
-      toast.error("필수 항목을 모두 입력해주세요.")
+    const validationErrors: string[] = []
+    
+    if (!form.name) validationErrors.push('계약명')
+    if (!form.category) validationErrors.push('계약구분')
+    if (!form.type) validationErrors.push('계약종류')
+    if (!form.executionMethod) validationErrors.push('체결방식')
+    if (!form.vendorId) validationErrors.push('협력업체')
+    
+    // AD, LO, OF 계약이 아닌 경우에만 계약기간 필수값 체크
+    if (!['AD', 'LO', 'OF'].includes(form.type)) {
+      if (!form.startDate) validationErrors.push('계약시작일')
+      if (!form.endDate) validationErrors.push('계약종료일')
+    }
+    
+    // LO 계약인 경우 계약체결유효기간 필수값 체크
+    if (form.type === 'LO' && !form.validityEndDate) {
+      validationErrors.push('유효기간')
+    }
+    
+    if (validationErrors.length > 0) {
+      toast.error(`다음 필수 항목을 입력해주세요: ${validationErrors.join(', ')}`)
       return
     }
 
@@ -116,7 +134,6 @@ export function CreateGeneralContractDialog() {
         category: form.category,
         type: form.type,
         executionMethod: form.executionMethod,
-        projectId: form.projectId,
         contractSourceType: 'manual',
         vendorId: form.vendorId!,
         startDate: form.startDate!.toISOString().split('T')[0],
@@ -152,7 +169,6 @@ export function CreateGeneralContractDialog() {
       type: '',
       executionMethod: '',
       vendorId: null,
-      projectId: null,
       startDate: undefined,
       endDate: undefined,
       validityEndDate: undefined,
@@ -231,15 +247,14 @@ export function CreateGeneralContractDialog() {
                       'AL': '연간운송계약',
                       'OS': '외주용역계약',
                       'OW': '도급계약',
-                      'IS': '검사계약',
                       'LO': 'LOI',
                       'FA': 'FA',
                       'SC': '납품합의계약',
                       'OF': '클레임상계계약',
                       'AW': '사전작업합의',
                       'AD': '사전납품합의',
-                      'AM': '설계계약',
-                      'SC_SELL': '폐기물매각계약'
+                      'SG': '임치(물품보관)계약',
+                      'SR': '폐기물매각계약'
                     }
                     return (
                       <SelectItem key={type} value={type}>
@@ -268,36 +283,63 @@ export function CreateGeneralContractDialog() {
             </div>
           </div>
 
-          <div className="grid gap-2">
-            <Label htmlFor="project">프로젝트</Label>
-            <Select value={form.projectId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, projectId: parseInt(value) }))}>
-              <SelectTrigger>
-                <SelectValue placeholder="프로젝트 선택 (선택사항)" />
-              </SelectTrigger>
-              <SelectContent>
-                {projects.map((project) => (
-                  <SelectItem key={project.id} value={project.id.toString()}>
-                    {project.name} ({project.code})
-                  </SelectItem>
-                ))}
-              </SelectContent>
-            </Select>
-          </div>
-
           <div className="grid gap-2">
             <Label htmlFor="vendor">협력업체 *</Label>
-            <Select value={form.vendorId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, vendorId: parseInt(value) }))}>
-              <SelectTrigger>
-                <SelectValue placeholder="협력업체 선택" />
-              </SelectTrigger>
-              <SelectContent>
-                {vendors.map((vendor) => (
-                  <SelectItem key={vendor.id} value={vendor.id.toString()}>
-                    {vendor.vendorName} ({vendor.vendorCode})
-                  </SelectItem>
-                ))}
-              </SelectContent>
-            </Select>
+            <Popover open={vendorOpen} onOpenChange={setVendorOpen}>
+              <PopoverTrigger asChild>
+                <Button
+                  variant="outline"
+                  role="combobox"
+                  aria-expanded={vendorOpen}
+                  className="w-full justify-between"
+                >
+                  {form.vendorId ? (
+                    (() => {
+                      const selected = vendors.find(v => v.id === form.vendorId)
+                      return selected ? `${selected.vendorName} (${selected.vendorCode || ''})` : "협력업체 선택"
+                    })()
+                  ) : (
+                    "협력업체 선택"
+                  )}
+                  <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
+                </Button>
+              </PopoverTrigger>
+              <PopoverContent className="w-[400px] p-0">
+                <Command>
+                  <CommandInput
+                    placeholder="협력업체명/코드 검색..."
+                    onValueChange={setVendorSearchTerm}
+                  />
+                  <CommandList className="max-h-[300px]">
+                    <CommandEmpty>검색 결과가 없습니다</CommandEmpty>
+                    <CommandGroup>
+                      {filteredVendors.map((vendor) => (
+                        <CommandItem
+                          key={vendor.id}
+                          value={`${vendor.vendorName} ${vendor.vendorCode || ''}`}
+                          onSelect={() => {
+                            setForm(prev => ({ ...prev, vendorId: vendor.id }))
+                            setVendorOpen(false)
+                            setVendorSearchTerm("")
+                          }}
+                        >
+                          <Check
+                            className={cn(
+                              "mr-2 h-4 w-4",
+                              form.vendorId === vendor.id ? "opacity-100" : "opacity-0"
+                            )}
+                          />
+                          <span className="font-medium">{vendor.vendorName}</span>
+                          {vendor.vendorCode && (
+                            <span className="ml-2 text-gray-500">({vendor.vendorCode})</span>
+                          )}
+                        </CommandItem>
+                      ))}
+                    </CommandGroup>
+                  </CommandList>
+                </Command>
+              </PopoverContent>
+            </Popover>
           </div>
 
           <div className="grid grid-cols-3 gap-4">
-- 
cgit v1.2.3

