From dfdfae3018f8499240f48d28ce634f4a5c56e006 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Wed, 2 Apr 2025 09:54:08 +0000 Subject: 벤더 코멘트 처리 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/pq/pq-input-tabs.tsx | 136 +++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 17 deletions(-) (limited to 'components/pq/pq-input-tabs.tsx') diff --git a/components/pq/pq-input-tabs.tsx b/components/pq/pq-input-tabs.tsx index 743e1729..b84d9167 100644 --- a/components/pq/pq-input-tabs.tsx +++ b/components/pq/pq-input-tabs.tsx @@ -54,7 +54,7 @@ import { FileListName, } from "@/components/ui/file-list" -// Dialog components from shadcn/ui +// Dialog components import { Dialog, DialogContent, @@ -65,13 +65,15 @@ import { } from "@/components/ui/dialog" // Additional UI -import { Separator } from "../ui/separator" +import { Separator } from "@/components/ui/separator" +import { Badge } from "@/components/ui/badge" -// Server actions (adjust to your actual code) +// Server actions import { uploadFileAction, savePQAnswersAction, submitPQAction, + ProjectPQ, } from "@/lib/pq/service" import { PQGroupData } from "@/lib/pq/service" @@ -132,9 +134,13 @@ type PQFormValues = z.infer export function PQInputTabs({ data, vendorId, + projectId, + projectData, }: { data: PQGroupData[] vendorId: number + projectId?: number + projectData?: ProjectPQ | null }) { const [isSaving, setIsSaving] = React.useState(false) const [isSubmitting, setIsSubmitting] = React.useState(false) @@ -152,7 +158,7 @@ export function PQInputTabs({ data.forEach((group) => { group.items.forEach((item) => { - // Check if the server item is already “complete” + // Check if the server item is already "complete" const hasExistingAnswer = item.answer && item.answer.trim().length > 0 const hasExistingAttachments = item.attachments && item.attachments.length > 0 @@ -190,7 +196,7 @@ export function PQInputTabs({ // ---------------------------------------------------------------------- React.useEffect(() => { const values = form.getValues() - // We consider items “saved” if `saved===true` AND they have an answer or attachments + // We consider items "saved" if `saved===true` AND they have an answer or attachments const allItemsSaved = values.answers.every( (answer) => answer.saved && (answer.answer || answer.uploadedFiles.length > 0) ) @@ -299,6 +305,7 @@ export function PQInputTabs({ const updatedAnswer = form.getValues(`answers.${answerIndex}`) const saveResult = await savePQAnswersAction({ vendorId, + projectId, // 프로젝트 ID 전달 answers: [ { criteriaId: updatedAnswer.criteriaId, @@ -396,13 +403,18 @@ export function PQInputTabs({ setIsSubmitting(true) setShowConfirmDialog(false) - const result = await submitPQAction(vendorId) + const result = await submitPQAction({ + vendorId, + projectId, // 프로젝트 ID 전달 + }) + if (result.ok) { toast({ title: "PQ Submitted", description: "Your PQ information has been submitted successfully", }) - // Optionally redirect + // 제출 후 페이지 새로고침 또는 리디렉션 처리 + window.location.reload() } else { toast({ title: "Submit Error", @@ -421,6 +433,72 @@ export function PQInputTabs({ setIsSubmitting(false) } } + + // 프로젝트 정보 표시 섹션 + const renderProjectInfo = () => { + if (!projectData) return null; + + return ( +
+
+

프로젝트 정보

+ + {getStatusLabel(projectData.status)} + +
+ +
+
+

프로젝트 코드

+

{projectData.projectCode}

+
+
+

프로젝트명

+

{projectData.projectName}

+
+ {projectData.submittedAt && ( +
+

제출일

+

{formatDate(projectData.submittedAt)}

+
+ )} +
+
+ ); + }; + + // 상태 표시용 함수 + const getStatusLabel = (status: string) => { + switch (status) { + case "REQUESTED": return "요청됨"; + case "IN_PROGRESS": return "진행중"; + case "SUBMITTED": return "제출됨"; + case "APPROVED": return "승인됨"; + case "REJECTED": return "반려됨"; + default: return status; + } + }; + + const getStatusVariant = (status: string) => { + switch (status) { + case "REQUESTED": return "secondary"; + case "IN_PROGRESS": return "default"; + case "SUBMITTED": return "outline"; + case "APPROVED": return "outline"; + case "REJECTED": return "destructive"; + default: return "secondary"; + } + }; + + // 날짜 형식화 함수 + const formatDate = (date: Date) => { + if (!date) return "-"; + return new Date(date).toLocaleDateString("ko-KR", { + year: "numeric", + month: "long", + day: "numeric", + }); + }; // ---------------------------------------------------------------------- // H) Render @@ -428,6 +506,9 @@ export function PQInputTabs({ return (
+ {/* 프로젝트 정보 섹션 */} + {renderProjectInfo()} + {/* Top Controls */}
@@ -485,7 +566,7 @@ export function PQInputTabs({ {/* 2-column grid */}
{group.items.map((item) => { - const { criteriaId, code, checkPoint, description } = item + const { criteriaId, code, checkPoint, description, contractInfo, additionalRequirement } = item const answerIndex = getAnswerIndex(criteriaId) if (answerIndex === -1) return null @@ -498,7 +579,7 @@ export function PQInputTabs({ const hasNewUploads = newUploads.length > 0 const canSave = isItemDirty || hasNewUploads - // For “Not Saved” vs. “Saved” status label + // For "Not Saved" vs. "Saved" status label const hasUploads = form.watch(`answers.${answerIndex}.uploadedFiles`).length > 0 || newUploads.length > 0 @@ -556,13 +637,32 @@ export function PQInputTabs({ - {/* Answer Field */} - + + {/* 프로젝트별 추가 필드 (contractInfo, additionalRequirement) */} + {projectId && contractInfo && ( +
+ 계약 정보 +
+ {contractInfo} +
+
+ )} + + {projectId && additionalRequirement && ( +
+ 추가 요구사항 +
+ {additionalRequirement} +
+
+ )} + + {/* Answer Field */} ( - + Answer