From e7818a457371849e29519497ebf046f385f05ab6 Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Mon, 15 Sep 2025 01:23:00 +0000 Subject: (김준회) AVL 기능 구현 1차 및 벤더풀 E/B 구분 개선 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/avl/table/project-avl-add-dialog.tsx | 779 +++++++++++++++++++++++++++++++ 1 file changed, 779 insertions(+) create mode 100644 lib/avl/table/project-avl-add-dialog.tsx (limited to 'lib/avl/table/project-avl-add-dialog.tsx') diff --git a/lib/avl/table/project-avl-add-dialog.tsx b/lib/avl/table/project-avl-add-dialog.tsx new file mode 100644 index 00000000..509e4258 --- /dev/null +++ b/lib/avl/table/project-avl-add-dialog.tsx @@ -0,0 +1,779 @@ +"use client" + +import * as React from "react" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Checkbox } from "@/components/ui/checkbox" +import { Textarea } from "@/components/ui/textarea" +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select" +import { toast } from "sonner" +import type { AvlVendorInfoInput, AvlDetailItem } from "../types" + +interface ProjectAvlAddDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + onAddItem: (item: Omit) => Promise + editingItem?: AvlDetailItem // 수정할 항목 (없으면 추가 모드) + onUpdateItem?: (id: number, item: Omit) => Promise // 수정 핸들러 +} + +export function ProjectAvlAddDialog({ open, onOpenChange, onAddItem, editingItem, onUpdateItem }: ProjectAvlAddDialogProps) { + const [formData, setFormData] = React.useState>({ + // 설계 정보 + equipBulkDivision: "EQUIP", + disciplineCode: "", + disciplineName: "", + + // 자재 정보 + materialNameCustomerSide: "", + + // 패키지 정보 + packageCode: "", + packageName: "", + + // 자재그룹 정보 + materialGroupCode: "", + materialGroupName: "", + + // 협력업체 정보 + vendorName: "", + vendorCode: "", + + // AVL 정보 + avlVendorName: "", + tier: "", + + // 제안방향 + ownerSuggestion: false, + shiSuggestion: false, + + // 위치 정보 + headquarterLocation: "", + manufacturingLocation: "", + + // FA 정보 + faTarget: false, + faStatus: "", + + // Agent 정보 + isAgent: false, + + // 계약 서명주체 + contractSignerName: "", + contractSignerCode: "", + + // SHI Qualification + shiAvl: false, + shiBlacklist: false, + shiBcc: false, + + // 기술영업 견적결과 + salesQuoteNumber: "", + quoteCode: "", + salesVendorInfo: "", + salesCountry: "", + totalAmount: "", + quoteReceivedDate: "", + + // 업체 실적 현황 + recentQuoteDate: "", + recentQuoteNumber: "", + recentOrderDate: "", + recentOrderNumber: "", + + // 기타 + remarks: "" + }) + + // 수정 모드일 때 폼 데이터 초기화 + React.useEffect(() => { + if (editingItem) { + setFormData({ + // 설계 정보 + equipBulkDivision: editingItem.equipBulkDivision === "EQUIP" ? "EQUIP" : "BULK", + disciplineCode: editingItem.disciplineCode || "", + disciplineName: editingItem.disciplineName || "", + + // 자재 정보 + materialNameCustomerSide: editingItem.materialNameCustomerSide || "", + + // 패키지 정보 + packageCode: editingItem.packageCode || "", + packageName: editingItem.packageName || "", + + // 자재그룹 정보 + materialGroupCode: editingItem.materialGroupCode || "", + materialGroupName: editingItem.materialGroupName || "", + + // 협력업체 정보 + vendorName: editingItem.vendorName || "", + vendorCode: editingItem.vendorCode || "", + + // AVL 정보 + avlVendorName: editingItem.avlVendorName || "", + tier: editingItem.tier || "", + + // 제안방향 + ownerSuggestion: editingItem.ownerSuggestion || false, + shiSuggestion: editingItem.shiSuggestion || false, + + // 위치 정보 + headquarterLocation: editingItem.headquarterLocation || "", + manufacturingLocation: editingItem.manufacturingLocation || "", + + // FA 정보 + faTarget: editingItem.faTarget || false, + faStatus: editingItem.faStatus || "", + + // Agent 정보 + isAgent: editingItem.isAgent || false, + + // 계약 서명주체 + contractSignerName: editingItem.contractSignerName || "", + contractSignerCode: editingItem.contractSignerCode || "", + + // SHI Qualification + shiAvl: editingItem.shiAvl || false, + shiBlacklist: editingItem.shiBlacklist || false, + shiBcc: editingItem.shiBcc || false, + + // 기술영업 견적결과 + salesQuoteNumber: editingItem.salesQuoteNumber || "", + quoteCode: editingItem.quoteCode || "", + salesVendorInfo: editingItem.salesVendorInfo || "", + salesCountry: editingItem.salesCountry || "", + totalAmount: editingItem.totalAmount || "", + quoteReceivedDate: editingItem.quoteReceivedDate || "", + + // 업체 실적 현황 + recentQuoteDate: editingItem.recentQuoteDate || "", + recentQuoteNumber: editingItem.recentQuoteNumber || "", + recentOrderDate: editingItem.recentOrderDate || "", + recentOrderNumber: editingItem.recentOrderNumber || "", + + // 기타 + remarks: editingItem.remarks || "" + }) + } + }, [editingItem]) + + const handleSubmit = async () => { + // 필수 필드 검증 + if (!formData.disciplineName || !formData.materialNameCustomerSide) { + toast.error("설계공종과 고객사 AVL 자재명은 필수 입력 항목입니다.") + return + } + + try { + if (editingItem && onUpdateItem) { + // 수정 모드 + await onUpdateItem(editingItem.id, formData) + } else { + // 추가 모드 + await onAddItem(formData) + } + + // 폼 초기화 (onAddItem에서 성공적으로 처리된 경우에만) + setFormData({ + // 설계 정보 + equipBulkDivision: "EQUIP", + disciplineCode: "", + disciplineName: "", + + // 자재 정보 + materialNameCustomerSide: "", + + // 패키지 정보 + packageCode: "", + packageName: "", + + // 자재그룹 정보 + materialGroupCode: "", + materialGroupName: "", + + // 협력업체 정보 + vendorName: "", + vendorCode: "", + + // AVL 정보 + avlVendorName: "", + tier: "", + + // 제안방향 + ownerSuggestion: false, + shiSuggestion: false, + + // 위치 정보 + headquarterLocation: "", + manufacturingLocation: "", + + // FA 정보 + faTarget: false, + faStatus: "", + + // Agent 정보 + isAgent: false, + + // 계약 서명주체 + contractSignerName: "", + contractSignerCode: "", + + // SHI Qualification + shiAvl: false, + shiBlacklist: false, + shiBcc: false, + + // 기술영업 견적결과 + salesQuoteNumber: "", + quoteCode: "", + salesVendorInfo: "", + salesCountry: "", + totalAmount: "", + quoteReceivedDate: "", + + // 업체 실적 현황 + recentQuoteDate: "", + recentQuoteNumber: "", + recentOrderDate: "", + recentOrderNumber: "", + + // 기타 + remarks: "" + } as Omit) + + onOpenChange(false) + } catch (error) { + // 에러 처리는 onAddItem에서 담당하므로 여기서는 아무것도 하지 않음 + } + } + + const handleCancel = () => { + setFormData({ + // 설계 정보 + equipBulkDivision: "EQUIP", + disciplineCode: "", + disciplineName: "", + + // 자재 정보 + materialNameCustomerSide: "", + + // 패키지 정보 + packageCode: "", + packageName: "", + + // 자재그룹 정보 + materialGroupCode: "", + materialGroupName: "", + + // 협력업체 정보 + vendorName: "", + vendorCode: "", + + // AVL 정보 + avlVendorName: "", + tier: "", + + // 제안방향 + ownerSuggestion: false, + shiSuggestion: false, + + // 위치 정보 + headquarterLocation: "", + manufacturingLocation: "", + + // FA 정보 + faTarget: false, + faStatus: "", + + // Agent 정보 + isAgent: false, + + // 계약 서명주체 + contractSignerName: "", + contractSignerCode: "", + + // SHI Qualification + shiAvl: false, + shiBlacklist: false, + shiBcc: false, + + // 기술영업 견적결과 + salesQuoteNumber: "", + quoteCode: "", + salesVendorInfo: "", + salesCountry: "", + totalAmount: "", + quoteReceivedDate: "", + + // 업체 실적 현황 + recentQuoteDate: "", + recentQuoteNumber: "", + recentOrderDate: "", + recentOrderNumber: "", + + // 기타 + remarks: "" + } as Omit) + onOpenChange(false) + } + + return ( + + + + {editingItem ? "프로젝트 AVL 항목 수정" : "프로젝트 AVL 항목 추가"} + + {editingItem + ? "AVL 항목을 수정합니다. 필수 항목을 입력해주세요." + : "새로운 AVL 항목을 추가합니다. 필수 항목을 입력해주세요." + } * 표시된 항목은 필수 입력사항입니다. + + +
+ {/* 기본 정보 */} +
+

기본 정보

+
+
+ + +
+
+ + setFormData(prev => ({ ...prev, disciplineCode: e.target.value }))} + placeholder="설계공종코드를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, disciplineName: e.target.value }))} + placeholder="설계공종명을 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, materialNameCustomerSide: e.target.value }))} + placeholder="고객사 AVL 자재명을 입력하세요" + /> +
+
+
+ + {/* 패키지 정보 */} +
+

패키지 정보

+
+
+ + setFormData(prev => ({ ...prev, packageCode: e.target.value }))} + placeholder="패키지 코드를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, packageName: e.target.value }))} + placeholder="패키지 명을 입력하세요" + /> +
+
+
+ + {/* 자재그룹 정보 */} +
+

자재그룹 정보

+
+
+ + setFormData(prev => ({ ...prev, materialGroupCode: e.target.value }))} + placeholder="자재그룹 코드를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, materialGroupName: e.target.value }))} + placeholder="자재그룹 명을 입력하세요" + /> +
+
+
+ + {/* 협력업체 정보 */} +
+

협력업체 정보

+
+
+ + setFormData(prev => ({ ...prev, vendorCode: e.target.value }))} + placeholder="협력업체 코드를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, vendorName: e.target.value }))} + placeholder="협력업체 명을 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, avlVendorName: e.target.value }))} + placeholder="AVL 등재업체명을 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, tier: e.target.value }))} + placeholder="등급을 입력하세요" + /> +
+
+
+ + {/* 제안방향 */} +
+

제안방향

+
+
+ + setFormData(prev => ({ ...prev, ownerSuggestion: !!checked })) + } + /> + +
+
+ + setFormData(prev => ({ ...prev, shiSuggestion: !!checked })) + } + /> + +
+
+
+ + {/* 위치 정보 */} +
+

위치 정보

+
+
+ + setFormData(prev => ({ ...prev, headquarterLocation: e.target.value }))} + placeholder="본사 위치를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, manufacturingLocation: e.target.value }))} + placeholder="제작/선적지를 입력하세요" + /> +
+
+
+ + {/* FA 정보 */} +
+

FA 정보

+
+
+ + setFormData(prev => ({ ...prev, faTarget: !!checked })) + } + /> + +
+
+ + setFormData(prev => ({ ...prev, faStatus: e.target.value }))} + placeholder="FA 현황을 입력하세요" + /> +
+
+
+ + {/* Agent 정보 */} +
+

Agent 정보

+
+ + setFormData(prev => ({ ...prev, isAgent: !!checked })) + } + /> + +
+
+ + {/* 계약 서명주체 */} +
+

계약 서명주체

+
+
+ + setFormData(prev => ({ ...prev, contractSignerCode: e.target.value }))} + placeholder="계약서명주체 코드를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, contractSignerName: e.target.value }))} + placeholder="계약서명주체 명을 입력하세요" + /> +
+
+
+ + {/* SHI Qualification */} +
+

SHI Qualification

+
+
+ + setFormData(prev => ({ ...prev, shiAvl: !!checked })) + } + /> + +
+
+ + setFormData(prev => ({ ...prev, shiBlacklist: !!checked })) + } + /> + +
+
+ + setFormData(prev => ({ ...prev, shiBcc: !!checked })) + } + /> + +
+
+
+ + {/* 기술영업 견적결과 */} +
+

기술영업 견적결과

+
+
+ + setFormData(prev => ({ ...prev, salesQuoteNumber: e.target.value }))} + placeholder="기술영업 견적번호를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, quoteCode: e.target.value }))} + placeholder="견적서 Code를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, salesVendorInfo: e.target.value }))} + placeholder="견적 협력업체 명을 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, salesCountry: e.target.value }))} + placeholder="국가를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, totalAmount: e.target.value }))} + placeholder="총 금액을 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, quoteReceivedDate: e.target.value }))} + placeholder="YYYY-MM-DD" + /> +
+
+
+ + {/* 업체 실적 현황 */} +
+

업체 실적 현황

+
+
+ + setFormData(prev => ({ ...prev, recentQuoteNumber: e.target.value }))} + placeholder="최근견적번호를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, recentQuoteDate: e.target.value }))} + placeholder="YYYY-MM-DD" + /> +
+
+ + setFormData(prev => ({ ...prev, recentOrderNumber: e.target.value }))} + placeholder="최근발주번호를 입력하세요" + /> +
+
+ + setFormData(prev => ({ ...prev, recentOrderDate: e.target.value }))} + placeholder="YYYY-MM-DD" + /> +
+
+
+ + {/* 기타 */} +
+

기타

+
+ +