From 8077419e40368dc703f94d558fc746b73fbc6702 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 19 Aug 2025 09:23:47 +0000 Subject: (최겸) 구매 PQ 비밀유지계약서 별첨 첨부파일 추가, 정규업체등록관리 개발 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../table/major-items-update-dialog.tsx | 245 +++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 lib/vendor-regular-registrations/table/major-items-update-dialog.tsx (limited to 'lib/vendor-regular-registrations/table/major-items-update-dialog.tsx') diff --git a/lib/vendor-regular-registrations/table/major-items-update-dialog.tsx b/lib/vendor-regular-registrations/table/major-items-update-dialog.tsx new file mode 100644 index 00000000..26741a1b --- /dev/null +++ b/lib/vendor-regular-registrations/table/major-items-update-dialog.tsx @@ -0,0 +1,245 @@ +"use client" + +import * as React from "react" +import { useState } from "react" +import { toast } from "sonner" +import { X, Plus, Search } from "lucide-react" + +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Badge } from "@/components/ui/badge" +import { Label } from "@/components/ui/label" +import { searchItemsForPQ } from "@/lib/items/service" +import { updateMajorItems } from "../service" + +// PQ 대상 품목 타입 정의 +interface PQItem { + itemCode: string + itemName: string +} + +interface MajorItemsUpdateDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + registrationId?: number + vendorName?: string + currentItems?: string | null + onSuccess?: () => void +} + +export function MajorItemsUpdateDialog({ + open, + onOpenChange, + registrationId, + vendorName, + currentItems, + onSuccess, +}: MajorItemsUpdateDialogProps) { + const [isLoading, setIsLoading] = useState(false) + const [selectedItems, setSelectedItems] = useState([]) + + // 아이템 검색 관련 상태 + const [itemSearchQuery, setItemSearchQuery] = useState("") + const [filteredItems, setFilteredItems] = useState([]) + const [showItemDropdown, setShowItemDropdown] = useState(false) + + // 기존 아이템들 파싱 및 초기화 + React.useEffect(() => { + if (open && currentItems) { + try { + const parsedItems = JSON.parse(currentItems) + if (Array.isArray(parsedItems)) { + setSelectedItems(parsedItems) + } + } catch (error) { + console.error("기존 주요품목 파싱 오류:", error) + setSelectedItems([]) + } + } else if (open) { + setSelectedItems([]) + } + }, [open, currentItems]) + + // 아이템 검색 필터링 + React.useEffect(() => { + if (itemSearchQuery.trim() === "") { + setFilteredItems([]) + setShowItemDropdown(false) + return + } + + const searchItems = async () => { + try { + const results = await searchItemsForPQ(itemSearchQuery) + setFilteredItems(results) + setShowItemDropdown(true) + } catch (error) { + console.error("아이템 검색 오류:", error) + toast.error("아이템 검색 중 오류가 발생했습니다.") + setFilteredItems([]) + setShowItemDropdown(false) + } + } + + // 디바운싱: 300ms 후에 검색 실행 + const timeoutId = setTimeout(searchItems, 300) + return () => clearTimeout(timeoutId) + }, [itemSearchQuery]) + + // 아이템 선택 함수 + const handleSelectItem = (item: PQItem) => { + // 이미 선택된 아이템인지 확인 + const isAlreadySelected = selectedItems.some(selectedItem => + selectedItem.itemCode === item.itemCode + ) + + if (!isAlreadySelected) { + setSelectedItems(prev => [...prev, item]) + } + + // 검색 초기화 + setItemSearchQuery("") + setFilteredItems([]) + setShowItemDropdown(false) + } + + // 아이템 제거 함수 + const handleRemoveItem = (itemCode: string) => { + setSelectedItems(prev => prev.filter(item => item.itemCode !== itemCode)) + } + + const handleSave = async () => { + if (!registrationId) { + toast.error("등록 ID가 없습니다.") + return + } + + setIsLoading(true) + try { + const result = await updateMajorItems( + registrationId, + JSON.stringify(selectedItems) + ) + + if (result.success) { + toast.success("주요품목이 업데이트되었습니다.") + onOpenChange(false) + onSuccess?.() + } else { + toast.error(result.error || "주요품목 업데이트에 실패했습니다.") + } + } catch (error) { + console.error("주요품목 업데이트 오류:", error) + toast.error("주요품목 업데이트 중 오류가 발생했습니다.") + } finally { + setIsLoading(false) + } + } + + return ( + + + + 주요품목 등록 + + {vendorName && `${vendorName}의 `}주요품목을 등록해주세요. + + + +
+ {/* 선택된 아이템들 표시 */} + {selectedItems.length > 0 && ( +
+ +
+ {selectedItems.map((item) => ( + + + {item.itemCode} - {item.itemName} + + + + ))} +
+
+ )} + + {/* 검색 입력 */} +
+ +
+
+ + setItemSearchQuery(e.target.value)} + className="pl-9" + /> +
+ + {/* 검색 결과 드롭다운 */} + {showItemDropdown && ( +
+ {filteredItems.length > 0 ? ( + filteredItems.map((item) => ( + + )) + ) : ( +
+ 검색 결과가 없습니다. +
+ )} +
+ )} +
+ +
+ 아이템 코드나 이름을 입력하여 검색하고 선택하세요. +
+
+
+ +
+ + +
+
+
+ ) +} -- cgit v1.2.3