From 9ceed79cf32c896f8a998399bf1b296506b2cd4a Mon Sep 17 00:00:00 2001 From: dujinkim Date: Tue, 8 Apr 2025 03:08:19 +0000 Subject: 로그인 및 미들웨어 처리. 구조 변경 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/rfqs/table/update-rfq-sheet.tsx | 169 +++++++++++++++++++++++++++++++----- 1 file changed, 146 insertions(+), 23 deletions(-) (limited to 'lib/rfqs/table/update-rfq-sheet.tsx') diff --git a/lib/rfqs/table/update-rfq-sheet.tsx b/lib/rfqs/table/update-rfq-sheet.tsx index 769f25e7..22ca2c37 100644 --- a/lib/rfqs/table/update-rfq-sheet.tsx +++ b/lib/rfqs/table/update-rfq-sheet.tsx @@ -37,31 +37,127 @@ import { Input } from "@/components/ui/input" import { Rfq, RfqWithItemCount } from "@/db/schema/rfq" import { RfqType, updateRfqSchema, type UpdateRfqSchema } from "../validations" -import { modifyRfq } from "../service" +import { modifyRfq, getBudgetaryRfqs } from "../service" import { ProjectSelector } from "@/components/ProjectSelector" import { type Project } from "../service" -import { BudgetaryRfqSelector } from "./BudgetaryRfqSelector" +import { ParentRfqSelector } from "./ParentRfqSelector" interface UpdateRfqSheetProps extends React.ComponentPropsWithRef { rfq: RfqWithItemCount | null - rfqType?: RfqType; } - -interface BudgetaryRfq { +// 부모 RFQ 정보 타입 정의 +interface ParentRfq { id: number; rfqCode: string; description: string | null; + rfqType: RfqType; + projectId: number | null; + projectCode: string | null; + projectName: string | null; } - -export function UpdateRfqSheet({ rfq,rfqType = RfqType.PURCHASE , ...props }: UpdateRfqSheetProps) { +export function UpdateRfqSheet({ rfq, ...props }: UpdateRfqSheetProps) { const [isUpdatePending, startUpdateTransition] = React.useTransition() const { data: session } = useSession() const userId = Number(session?.user?.id || 1) - const [selectedBudgetaryRfq, setSelectedBudgetaryRfq] = React.useState(null) + const [selectedParentRfq, setSelectedParentRfq] = React.useState(null) + + // RFQ의 타입 가져오기 + const rfqType = rfq?.rfqType || RfqType.PURCHASE; + + // 초기 부모 RFQ ID 가져오기 + const initialParentRfqId = rfq?.parentRfqId; + + // 현재 RFQ 타입에 따라 선택 가능한 부모 RFQ 타입들 결정 + const getParentRfqTypes = (): RfqType[] => { + switch(rfqType) { + case RfqType.PURCHASE: + // PURCHASE는 BUDGETARY와 PURCHASE_BUDGETARY를 부모로 가질 수 있음 + return [RfqType.BUDGETARY, RfqType.PURCHASE_BUDGETARY]; + case RfqType.PURCHASE_BUDGETARY: + // PURCHASE_BUDGETARY는 BUDGETARY만 부모로 가질 수 있음 + return [RfqType.BUDGETARY]; + default: + return []; + } + }; + + // 부모 RFQ 타입들 + const parentRfqTypes = getParentRfqTypes(); + + // 부모 RFQ를 보여줄지 결정 + const shouldShowParentRfqSelector = rfqType === RfqType.PURCHASE || rfqType === RfqType.PURCHASE_BUDGETARY; + + // 타입에 따른 타이틀 생성 + const getTypeTitle = () => { + switch(rfqType) { + case RfqType.PURCHASE: + return "Purchase RFQ"; + case RfqType.BUDGETARY: + return "Budgetary RFQ"; + case RfqType.PURCHASE_BUDGETARY: + return "Purchase Budgetary RFQ"; + default: + return "RFQ"; + } + }; + + // 타입 설명 가져오기 + const getTypeDescription = () => { + switch(rfqType) { + case RfqType.PURCHASE: + return "실제 구매 발주 전에 가격을 요청"; + case RfqType.BUDGETARY: + return "기술영업 단계에서 입찰가 산정을 위한 견적 요청"; + case RfqType.PURCHASE_BUDGETARY: + return "프로젝트 수주 후, 공식 입찰 전 예산 책정을 위한 가격 요청"; + default: + return ""; + } + }; + // 부모 RFQ 선택기 레이블 및 설명 가져오기 + const getParentRfqSelectorLabel = () => { + if (rfqType === RfqType.PURCHASE) { + return "부모 RFQ (BUDGETARY/PURCHASE_BUDGETARY)"; + } else if (rfqType === RfqType.PURCHASE_BUDGETARY) { + return "부모 RFQ (BUDGETARY)"; + } + return "부모 RFQ"; + }; + + const getParentRfqDescription = () => { + if (rfqType === RfqType.PURCHASE) { + return "BUDGETARY 또는 PURCHASE_BUDGETARY 타입의 RFQ를 부모로 선택할 수 있습니다."; + } else if (rfqType === RfqType.PURCHASE_BUDGETARY) { + return "BUDGETARY 타입의 RFQ만 부모로 선택할 수 있습니다."; + } + return ""; + }; + + // 초기 부모 RFQ 로드 + React.useEffect(() => { + if (initialParentRfqId && shouldShowParentRfqSelector) { + const loadInitialParentRfq = async () => { + try { + const result = await getBudgetaryRfqs({ + rfqId: initialParentRfqId + }); + + if ('rfqs' in result && result.rfqs && result.rfqs.length > 0) { + setSelectedParentRfq(result.rfqs[0] as unknown as ParentRfq); + } + } catch (error) { + console.error("부모 RFQ 로드 오류:", error); + } + }; + + loadInitialParentRfq(); + } + }, [initialParentRfqId, shouldShowParentRfqSelector]); + // RHF setup const form = useForm({ resolver: zodResolver(updateRfqSchema), @@ -70,6 +166,7 @@ export function UpdateRfqSheet({ rfq,rfqType = RfqType.PURCHASE , ...props }: Up rfqCode: rfq?.rfqCode ?? "", description: rfq?.description ?? "", projectId: rfq?.projectId, // 프로젝트 ID + parentRfqId: rfq?.parentRfqId, // 부모 RFQ ID dueDate: rfq?.dueDate ?? undefined, // null을 undefined로 변환 status: rfq?.status ?? "DRAFT", createdBy: rfq?.createdBy ?? userId, @@ -77,16 +174,27 @@ export function UpdateRfqSheet({ rfq,rfqType = RfqType.PURCHASE , ...props }: Up }); // 프로젝트 선택 처리 - const handleProjectSelect = (project: Project) => { + const handleProjectSelect = (project: Project | null) => { + if (project === null) { + return; + } form.setValue("projectId", project.id); }; + // 부모 RFQ 선택 처리 + const handleParentRfqSelect = (rfq: ParentRfq | null) => { + setSelectedParentRfq(rfq); + form.setValue("parentRfqId", rfq?.id); + }; + async function onSubmit(input: UpdateRfqSchema) { startUpdateTransition(async () => { if (!rfq) return const { error } = await modifyRfq({ ...input, + rfqType: rfqType as RfqType, + }) if (error) { @@ -104,9 +212,12 @@ export function UpdateRfqSheet({ rfq,rfqType = RfqType.PURCHASE , ...props }: Up - Update RFQ + Update {getTypeTitle()} - Update the RFQ details and save the changes + Update the {getTypeTitle()} details and save the changes +
+ {getTypeDescription()} +
@@ -122,6 +233,15 @@ export function UpdateRfqSheet({ rfq,rfqType = RfqType.PURCHASE , ...props }: Up )} /> + + {/* Hidden rfqType field */} + {/* ( + + )} + /> */} {/* Project Selector - 재사용 컴포넌트 사용 */} - {/* Budgetary RFQ Selector - 구매용 RFQ 생성 시에만 표시 */} - {rfqType === RfqType.PURCHASE && ( + {/* Parent RFQ Selector - PURCHASE 또는 PURCHASE_BUDGETARY 타입일 때만 표시 */} + {shouldShowParentRfqSelector && ( ( - Budgetary RFQ (Optional) + {getParentRfqSelectorLabel()} - { - setSelectedBudgetaryRfq(rfq as any); - form.setValue("parentRfqId", rfq?.id); - }} - placeholder="Budgetary RFQ 선택..." + onRfqSelect={handleParentRfqSelect} + rfqType={rfqType} + parentRfqTypes={parentRfqTypes} + placeholder={ + rfqType === RfqType.PURCHASE + ? "BUDGETARY 또는 PURCHASE_BUDGETARY RFQ 선택..." + : "BUDGETARY RFQ 선택..." + } /> +
+ {getParentRfqDescription()} +
)} /> )} - {/* rfqCode */} - - {/* dueDate (type="date") */}