From 8440ac29c7dcbef992039678ecc0fabff2fd04ec Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 1 Dec 2025 00:58:23 +0000
Subject: (대표님) S-EDP 관련 대표님 작업사항
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 components/form-data-plant/publish-dialog.tsx | 226 ++++++++++++++++----------
 1 file changed, 136 insertions(+), 90 deletions(-)

(limited to 'components/form-data-plant/publish-dialog.tsx')

diff --git a/components/form-data-plant/publish-dialog.tsx b/components/form-data-plant/publish-dialog.tsx
index a3a2ef0b..f63c2db8 100644
--- a/components/form-data-plant/publish-dialog.tsx
+++ b/components/form-data-plant/publish-dialog.tsx
@@ -37,19 +37,21 @@ import { Loader2, Check, ChevronsUpDown } from "lucide-react";
 import { toast } from "sonner";
 import { cn } from "@/lib/utils";
 import { 
-  createRevisionAction, 
-  fetchDocumentsByPackageId, 
-  fetchStagesByDocumentId, 
-  fetchRevisionsByStageParams,
-  Document,
-  IssueStage,
-  Revision
+  createSubmissionAction, // 새로운 액션 이름
+  fetchDocumentsByProjectAndPackage, // 업데이트된 액션
+  fetchStagesByDocumentIdPlant, 
+  fetchSubmissionsByStageParams, // revisions 대신 submissions
 } from "@/lib/vendor-document/service";
+import type { 
+  StageDocument,
+  StageIssueStage,
+} from "@/db/schema/vendorDocu";
 
 interface PublishDialogProps {
   open: boolean;
   onOpenChange: (open: boolean) => void;
-  packageId: number;
+  projectCode: string;
+  packageCode: string;
   formCode: string;
   fileBlob?: Blob;
 }
@@ -57,7 +59,8 @@ interface PublishDialogProps {
 export const PublishDialog: React.FC<PublishDialogProps> = ({
   open,
   onOpenChange,
-  packageId,
+  projectCode,
+  packageCode,
   formCode,
   fileBlob,
 }) => {
@@ -65,9 +68,10 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
   const { data: session } = useSession();
   
   // State for form data
-  const [documents, setDocuments] = useState<Document[]>([]);
-  const [stages, setStages] = useState<IssueStage[]>([]);
-  const [latestRevision, setLatestRevision] = useState<string>("");
+  const [documents, setDocuments] = useState<StageDocument[]>([]);
+  const [stages, setStages] = useState<StageIssueStage[]>([]);
+  const [latestRevisionCode, setLatestRevisionCode] = useState<string>("");
+  const [latestRevisionNumber, setLatestRevisionNumber] = useState<number>(0);
   
   // State for document search
   const [openDocumentCombobox, setOpenDocumentCombobox] = useState(false);
@@ -77,9 +81,10 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
   const [selectedDocId, setSelectedDocId] = useState<string>("");
   const [selectedDocumentDisplay, setSelectedDocumentDisplay] = useState<string>("");
   const [selectedStage, setSelectedStage] = useState<string>("");
-  const [revisionInput, setRevisionInput] = useState<string>("");
-  const [uploaderName, setUploaderName] = useState<string>("");
-  const [comment, setComment] = useState<string>("");
+  const [revisionCodeInput, setRevisionCodeInput] = useState<string>("");
+  const [submitterName, setSubmitterName] = useState<string>("");
+  const [submissionTitle, setSubmissionTitle] = useState<string>("");
+  const [submissionDescription, setSubmissionDescription] = useState<string>("");
   const [customFileName, setCustomFileName] = useState<string>(`${formCode}_document.docx`);
   
   // Loading states
@@ -94,10 +99,10 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
       )
     : documents;
   
-  // Set uploader name from session when dialog opens
+  // Set submitter name from session when dialog opens
   useEffect(() => {
     if (open && session?.user?.name) {
-      setUploaderName(session.user.name);
+      setSubmitterName(session.user.name);
     }
   }, [open, session]);
   
@@ -107,24 +112,26 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
       setSelectedDocId("");
       setSelectedDocumentDisplay("");
       setSelectedStage("");
-      setRevisionInput("");
-      // Only set uploaderName if not already set from session
-      if (!session?.user?.name) setUploaderName("");
-      setComment("");
-      setLatestRevision("");
+      setRevisionCodeInput("");
+      setSubmissionTitle("");
+      setSubmissionDescription("");
+      // Only set submitterName if not already set from session
+      if (!session?.user?.name) setSubmitterName("");
+      setLatestRevisionCode("");
+      setLatestRevisionNumber(0);
       setCustomFileName(`${formCode}_document.docx`);
       setDocumentSearchValue("");
     }
   }, [open, formCode, session]);
   
-  // Fetch documents based on packageId
+  // Fetch documents based on projectCode and packageCode
   useEffect(() => {
     async function loadDocuments() {
-      if (packageId && open) {
+      if (projectCode && packageCode && open) {
         setIsLoading(true);
         
         try {
-          const docs = await fetchDocumentsByPackageId(packageId);
+          const docs = await fetchDocumentsByProjectAndPackage(projectCode, packageCode);
           setDocuments(docs);
         } catch (error) {
           console.error("Error fetching documents:", error);
@@ -136,7 +143,7 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
     }
     
     loadDocuments();
-  }, [packageId, open]);
+  }, [projectCode, packageCode, open]);
   
   // Fetch stages when document is selected
   useEffect(() => {
@@ -146,11 +153,12 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
         
         // Reset dependent fields
         setSelectedStage("");
-        setRevisionInput("");
-        setLatestRevision("");
+        setRevisionCodeInput("");
+        setLatestRevisionCode("");
+        setLatestRevisionNumber(0);
         
         try {
-          const stagesList = await fetchStagesByDocumentId(parseInt(selectedDocId, 10));
+          const stagesList = await fetchStagesByDocumentIdPlant(parseInt(selectedDocId, 10));
           setStages(stagesList);
         } catch (error) {
           console.error("Error fetching stages:", error);
@@ -166,65 +174,78 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
     loadStages();
   }, [selectedDocId]);
   
-  // Fetch latest revision when stage is selected (for reference)
+  // Fetch latest submission (revision) when stage is selected
   useEffect(() => {
-    async function loadLatestRevision() {
+    async function loadLatestSubmission() {
       if (selectedDocId && selectedStage) {
         setIsLoading(true);
         
         try {
-          const revsList = await fetchRevisionsByStageParams(
+          const submissionsList = await fetchSubmissionsByStageParams(
             parseInt(selectedDocId, 10), 
             selectedStage
           );
           
-          // Find the latest revision (assuming revisions are sorted by revision number)
-          if (revsList.length > 0) {
-            // Sort revisions if needed
-            const sortedRevisions = [...revsList].sort((a, b) => {
-              return b.revision.localeCompare(a.revision, undefined, { numeric: true });
-            });
+          // Find the latest submission (assuming sorted by revision number)
+          if (submissionsList.length > 0) {
+            // Sort submissions by revision number descending
+            const sortedSubmissions = [...submissionsList].sort((a, b) => 
+              b.revisionNumber - a.revisionNumber
+            );
             
-            setLatestRevision(sortedRevisions[0].revision);
+            const latestSubmission = sortedSubmissions[0];
+            setLatestRevisionCode(latestSubmission.revisionCode);
+            setLatestRevisionNumber(latestSubmission.revisionNumber);
             
-            // Pre-fill the revision input with an incremented value if possible
-            if (sortedRevisions[0].revision.match(/^\d+$/)) {
+            // Auto-increment revision code
+            if (latestSubmission.revisionCode.match(/^\d+$/)) {
               // If it's a number, increment it
-              const nextRevision = String(parseInt(sortedRevisions[0].revision, 10) + 1);
-              setRevisionInput(nextRevision);
-            } else if (sortedRevisions[0].revision.match(/^[A-Za-z]$/)) {
+              const nextRevision = String(parseInt(latestSubmission.revisionCode, 10) + 1);
+              setRevisionCodeInput(nextRevision);
+            } else if (latestSubmission.revisionCode.match(/^[A-Za-z]$/)) {
               // If it's a single letter, get the next letter
-              const currentChar = sortedRevisions[0].revision.charCodeAt(0);
+              const currentChar = latestSubmission.revisionCode.charCodeAt(0);
               const nextChar = String.fromCharCode(currentChar + 1);
-              setRevisionInput(nextChar);
+              setRevisionCodeInput(nextChar);
+            } else if (latestSubmission.revisionCode.toLowerCase().startsWith("rev")) {
+              // Handle "Rev0", "Rev1" format
+              const numMatch = latestSubmission.revisionCode.match(/\d+$/);
+              if (numMatch) {
+                const nextNum = parseInt(numMatch[0], 10) + 1;
+                setRevisionCodeInput(`Rev${nextNum}`);
+              } else {
+                setRevisionCodeInput("");
+              }
             } else {
               // For other formats, just show the latest as reference
-              setRevisionInput("");
+              setRevisionCodeInput("");
             }
           } else {
-            // If no revisions exist, set default values
-            setLatestRevision("");
-            setRevisionInput("0");
+            // If no submissions exist, set default values
+            setLatestRevisionCode("");
+            setLatestRevisionNumber(0);
+            setRevisionCodeInput("Rev0"); // Start with Rev0
           }
         } catch (error) {
-          console.error("Error fetching revisions:", error);
-          toast.error("Failed to load revision information");
+          console.error("Error fetching submissions:", error);
+          toast.error("Failed to load submission information");
         } finally {
           setIsLoading(false);
         }
       } else {
-        setLatestRevision("");
-        setRevisionInput("");
+        setLatestRevisionCode("");
+        setLatestRevisionNumber(0);
+        setRevisionCodeInput("");
       }
     }
     
-    loadLatestRevision();
+    loadLatestSubmission();
   }, [selectedDocId, selectedStage]);
   
   const handleSubmit = async (e: React.FormEvent) => {
     e.preventDefault();
     
-    if (!selectedDocId || !selectedStage || !revisionInput || !fileBlob) {
+    if (!selectedDocId || !selectedStage || !revisionCodeInput || !fileBlob) {
       toast.error("Please fill in all required fields");
       return;
     }
@@ -235,17 +256,30 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
       // Create FormData
       const formData = new FormData();
       formData.append("documentId", selectedDocId);
-      formData.append("stage", selectedStage);
-      formData.append("revision", revisionInput);
+      formData.append("stageName", selectedStage);
+      formData.append("revisionCode", revisionCodeInput);
       formData.append("customFileName", customFileName);
-      formData.append("uploaderType", "vendor"); // Default value
       
-      if (uploaderName) {
-        formData.append("uploaderName", uploaderName);
+      if (submitterName) {
+        formData.append("submittedBy", submitterName);
       }
       
-      if (comment) {
-        formData.append("comment", comment);
+      if (session?.user?.email) {
+        formData.append("submittedByEmail", session.user.email);
+      }
+      
+      if (submissionTitle) {
+        formData.append("submissionTitle", submissionTitle);
+      }
+      
+      if (submissionDescription) {
+        formData.append("submissionDescription", submissionDescription);
+      }
+      
+      // Get vendor info from selected document
+      const selectedDoc = documents.find(doc => doc.id === parseInt(selectedDocId, 10));
+      if (selectedDoc) {
+        formData.append("vendorId", String(selectedDoc.vendorId));
       }
       
       // Append file as attachment
@@ -256,12 +290,14 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
         formData.append("attachment", file);
       }
       
-      // Call server action directly
-      const result = await createRevisionAction(formData);
+      // Call server action
+      const result = await createSubmissionAction(formData);
       
-      if (result) {
+      if (result.success) {
         toast.success("Document published successfully!");
         onOpenChange(false);
+      } else {
+        toast.error(result.error || "Failed to publish document");
       }
     } catch (error) {
       console.error("Error publishing document:", error);
@@ -301,7 +337,6 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
                       className="w-full justify-between"
                       disabled={isLoading || documents.length === 0}
                     >
-                      {/* Add text-overflow handling for selected document display */}
                       <span className="truncate">
                         {selectedDocumentDisplay 
                           ? selectedDocumentDisplay 
@@ -338,7 +373,6 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
                                   : "opacity-0"
                               )}
                             />
-                            {/* Add text-overflow handling for document items */}
                             <span className="truncate">{doc.docNumber} - {doc.title}</span>
                           </CommandItem>
                         ))}
@@ -366,7 +400,6 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
                   <SelectContent>
                     {stages.map((stage) => (
                       <SelectItem key={stage.id} value={stage.stageName}>
-                        {/* Add text-overflow handling for stage names */}
                         <span className="truncate">{stage.stageName}</span>
                       </SelectItem>
                     ))}
@@ -375,27 +408,41 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
               </div>
             </div>
             
-            {/* Revision Input */}
+            {/* Revision Code Input */}
             <div className="grid grid-cols-4 items-center gap-4">
-              <Label htmlFor="revision" className="text-right">
+              <Label htmlFor="revisionCode" className="text-right">
                 Revision
               </Label>
               <div className="col-span-3">
                 <Input
-                  id="revision"
-                  value={revisionInput}
-                  onChange={(e) => setRevisionInput(e.target.value)}
-                  placeholder="Enter revision"
+                  id="revisionCode"
+                  value={revisionCodeInput}
+                  onChange={(e) => setRevisionCodeInput(e.target.value)}
+                  placeholder="Enter revision code (e.g., Rev0, A, 1)"
                   disabled={isLoading || !selectedStage}
                 />
-                {latestRevision && (
+                {latestRevisionCode && (
                   <p className="text-xs text-muted-foreground mt-1">
-                    Latest revision: {latestRevision}
+                    Latest revision: {latestRevisionCode} (#{latestRevisionNumber})
                   </p>
                 )}
               </div>
             </div>
             
+            <div className="grid grid-cols-4 items-center gap-4">
+              <Label htmlFor="submissionTitle" className="text-right">
+                Title
+              </Label>
+              <div className="col-span-3">
+                <Input
+                  id="submissionTitle"
+                  value={submissionTitle}
+                  onChange={(e) => setSubmissionTitle(e.target.value)}
+                  placeholder="Optional submission title"
+                />
+              </div>
+            </div>
+            
             <div className="grid grid-cols-4 items-center gap-4">
               <Label htmlFor="fileName" className="text-right">
                 File Name
@@ -411,16 +458,15 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
             </div>
             
             <div className="grid grid-cols-4 items-center gap-4">
-              <Label htmlFor="uploaderName" className="text-right">
-                Uploader
+              <Label htmlFor="submitterName" className="text-right">
+                Submitter
               </Label>
               <div className="col-span-3">
                 <Input
-                  id="uploaderName"
-                  value={uploaderName}
-                  onChange={(e) => setUploaderName(e.target.value)}
+                  id="submitterName"
+                  value={submitterName}
+                  onChange={(e) => setSubmitterName(e.target.value)}
                   placeholder="Your name"
-                  // Disable input but show a filled style
                   className={session?.user?.name ? "opacity-70" : ""}
                   readOnly={!!session?.user?.name}
                 />
@@ -433,15 +479,15 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
             </div>
             
             <div className="grid grid-cols-4 items-center gap-4">
-              <Label htmlFor="comment" className="text-right">
-                Comment
+              <Label htmlFor="description" className="text-right">
+                Description
               </Label>
               <div className="col-span-3">
                 <Textarea
-                  id="comment"
-                  value={comment}
-                  onChange={(e) => setComment(e.target.value)}
-                  placeholder="Optional comment"
+                  id="description"
+                  value={submissionDescription}
+                  onChange={(e) => setSubmissionDescription(e.target.value)}
+                  placeholder="Optional submission description"
                   className="resize-none"
                 />
               </div>
@@ -451,7 +497,7 @@ export const PublishDialog: React.FC<PublishDialogProps> = ({
           <DialogFooter>
             <Button 
               type="submit" 
-              disabled={isSubmitting || !selectedDocId || !selectedStage || !revisionInput}
+              disabled={isSubmitting || !selectedDocId || !selectedStage || !revisionCodeInput}
             >
               {isSubmitting ? (
                 <>
-- 
cgit v1.2.3

