From 7a1524ba54f43d0f2a19e4bca2c6a2e0b01c5ef1 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 17 Jun 2025 09:02:32 +0000 Subject: (대표님) 20250617 18시 작업사항 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/b-rfq/initial/add-initial-rfq-dialog.tsx | 326 +++++++++++++++------------ 1 file changed, 188 insertions(+), 138 deletions(-) (limited to 'lib/b-rfq/initial/add-initial-rfq-dialog.tsx') diff --git a/lib/b-rfq/initial/add-initial-rfq-dialog.tsx b/lib/b-rfq/initial/add-initial-rfq-dialog.tsx index d0924be2..58a091ac 100644 --- a/lib/b-rfq/initial/add-initial-rfq-dialog.tsx +++ b/lib/b-rfq/initial/add-initial-rfq-dialog.tsx @@ -1,4 +1,3 @@ -// add-initial-rfq-dialog.tsx "use client" import * as React from "react" @@ -45,6 +44,7 @@ import { Checkbox } from "@/components/ui/checkbox" import { cn, formatDate } from "@/lib/utils" import { addInitialRfqRecord, getIncotermsForSelection, getVendorsForSelection } from "../service" import { Calendar } from "@/components/ui/calendar" +import { InitialRfqDetailView } from "@/db/schema" // Initial RFQ 추가 폼 스키마 const addInitialRfqSchema = z.object({ @@ -70,22 +70,30 @@ const addInitialRfqSchema = z.object({ returnRevision: z.number().default(0), }) -type AddInitialRfqFormData = z.infer +export type AddInitialRfqFormData = z.infer interface Vendor { id: number vendorName: string vendorCode: string country: string + taxId: string status: string } +interface Incoterm { + id: number + code: string + description: string +} + interface AddInitialRfqDialogProps { rfqId: number onSuccess?: () => void + defaultValues?: InitialRfqDetailView // 선택된 항목의 기본값 } -export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogProps) { +export function AddInitialRfqDialog({ rfqId, onSuccess, defaultValues }: AddInitialRfqDialogProps) { const [open, setOpen] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false) const [vendors, setVendors] = React.useState([]) @@ -95,16 +103,38 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro const [incotermsLoading, setIncotermsLoading] = React.useState(false) const [incotermsSearchOpen, setIncotermsSearchOpen] = React.useState(false) - const form = useForm({ - resolver: zodResolver(addInitialRfqSchema), - defaultValues: { + // 기본값 설정 (선택된 항목이 있으면 해당 값 사용, 없으면 일반 기본값) + const getDefaultFormValues = React.useCallback((): Partial => { + if (defaultValues) { + return { + vendorId: defaultValues.vendorId, + initialRfqStatus: "DRAFT", // 새로 추가할 때는 항상 DRAFT로 시작 + dueDate: defaultValues.dueDate || new Date(), + validDate: defaultValues.validDate, + incotermsCode: defaultValues.incotermsCode || "", + classification: defaultValues.classification || "", + sparepart: defaultValues.sparepart || "", + shortList: false, // 새로 추가할 때는 기본적으로 false + returnYn: false, + cpRequestYn: defaultValues.cpRequestYn || false, + prjectGtcYn: defaultValues.prjectGtcYn || false, + returnRevision: 0, + } + } + + return { initialRfqStatus: "DRAFT", shortList: false, returnYn: false, cpRequestYn: false, prjectGtcYn: false, returnRevision: 0, - }, + } + }, [defaultValues]) + + const form = useForm({ + resolver: zodResolver(addInitialRfqSchema), + defaultValues: getDefaultFormValues(), }) // 벤더 목록 로드 @@ -121,23 +151,27 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro } }, []) - // Incoterms 목록 로드 - const loadIncoterms = React.useCallback(async () => { - setIncotermsLoading(true) - try { - const incotermsList = await getIncotermsForSelection() - setIncoterms(incotermsList) - } catch (error) { - console.error("Failed to load incoterms:", error) - toast.error("Incoterms 목록을 불러오는데 실패했습니다.") - } finally { - setIncotermsLoading(false) - } - }, []) + // Incoterms 목록 로드 + const loadIncoterms = React.useCallback(async () => { + setIncotermsLoading(true) + try { + const incotermsList = await getIncotermsForSelection() + setIncoterms(incotermsList) + } catch (error) { + console.error("Failed to load incoterms:", error) + toast.error("Incoterms 목록을 불러오는데 실패했습니다.") + } finally { + setIncotermsLoading(false) + } + }, []) - // 다이얼로그 열릴 때 벤더 목록 로드 + // 다이얼로그 열릴 때 실행 React.useEffect(() => { if (open) { + // 폼을 기본값으로 리셋 + form.reset(getDefaultFormValues()) + + // 데이터 로드 if (vendors.length === 0) { loadVendors() } @@ -145,12 +179,12 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro loadIncoterms() } } - }, [open, vendors.length, incoterms.length, loadVendors, loadIncoterms]) + }, [open, vendors.length, incoterms.length, loadVendors, loadIncoterms, form, getDefaultFormValues]) // 다이얼로그 닫기 핸들러 const handleOpenChange = (newOpen: boolean) => { if (!newOpen && !isSubmitting) { - form.reset() + form.reset(getDefaultFormValues()) } setOpen(newOpen) } @@ -167,7 +201,7 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro if (result.success) { toast.success(result.message || "초기 RFQ가 성공적으로 추가되었습니다.") - form.reset() + form.reset(getDefaultFormValues()) handleOpenChange(false) onSuccess?.() } else { @@ -186,20 +220,32 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro const selectedVendor = vendors.find(vendor => vendor.id === form.watch("vendorId")) const selectedIncoterm = incoterms.find(incoterm => incoterm.code === form.watch("incotermsCode")) + // 기본값이 있을 때 버튼 텍스트 변경 + const buttonText = defaultValues ? "유사 항목 추가" : "초기 RFQ 추가" + const dialogTitle = defaultValues ? "유사 초기 RFQ 추가" : "초기 RFQ 추가" + const dialogDescription = defaultValues + ? "선택된 항목을 기본값으로 하여 새로운 초기 RFQ를 추가합니다." + : "새로운 벤더를 대상으로 하는 초기 RFQ를 추가합니다." + return ( - 초기 RFQ 추가 + {dialogTitle} - 새로운 벤더를 대상으로 하는 초기 RFQ를 추가합니다. + {dialogDescription} + {defaultValues && ( +
+ 기본값 출처: {defaultValues.vendorName} ({defaultValues.vendorCode}) +
+ )}
@@ -263,7 +309,7 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro {vendor.vendorName}
- {vendor.vendorCode} • {vendor.country} + {vendor.vendorCode} • {vendor.country} • {vendor.taxId}
- ( - - 견적 마감일 - - - - - - - - - date < new Date() || date < new Date("1900-01-01") - } - initialFocus - /> - - - - - )} - /> - ( - - 견적 유효일 - - - - - - - - - date < new Date() || date < new Date("1900-01-01") - } - initialFocus - /> - - - - - )} - /> + ( + + 견적 마감일 * + + + + + + + + + date < new Date() || date < new Date("1900-01-01") + } + initialFocus + /> + + + + + )} + /> + + ( + + 견적 유효일 + + + + + + + + + date < new Date() || date < new Date("1900-01-01") + } + initialFocus + /> + + + + + )} + /> - {/* Incoterms 및 GTC */} -
+ {/* Incoterms 선택 */} ( - Incoterms * + Incoterms @@ -391,9 +437,8 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro > {selectedIncoterm ? (
- - {selectedIncoterm.code} ({selectedIncoterm.description}) + {selectedIncoterm.code} - {selectedIncoterm.description}
) : ( @@ -419,18 +464,20 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro key={incoterm.id} value={`${incoterm.code} ${incoterm.description}`} onSelect={() => { - field.onChange(vendor.id) - setVendorSearchOpen(false) + field.onChange(incoterm.code) + setIncotermsSearchOpen(false) }} >
+
- {incoterm.code} {incoterm.description} + {incoterm.code} - {incoterm.description}
+
@@ -445,34 +492,41 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro
)} /> -
- {/* GTC 정보 */} + {/* 옵션 체크박스 */}
( - - GTC + - + - +
+ CP 요청 +
)} /> ( - - GTC 유효일 + - + - +
+ Project용 GTC 사용 +
)} /> @@ -501,7 +555,7 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro Spare part - + @@ -509,8 +563,6 @@ export function AddInitialRfqDialog({ rfqId, onSuccess }: AddInitialRfqDialogPro />
- -
) -} - - +} \ No newline at end of file -- cgit v1.2.3