From 8a19a6fa336768d8b6712752c9d713360067ecb0 Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 8 Dec 2025 08:45:20 +0000
Subject: (최겸) 구매 피드백 수정, 안전담당자, pq항목 내 첨부, 내외자 구분,
 도로명주소 api 반영(운영기준)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/pq/pq-criteria/add-pq-dialog.tsx | 145 ++++++++++++++++++++++++++++++++++-
 1 file changed, 142 insertions(+), 3 deletions(-)

(limited to 'lib/pq/pq-criteria/add-pq-dialog.tsx')

diff --git a/lib/pq/pq-criteria/add-pq-dialog.tsx b/lib/pq/pq-criteria/add-pq-dialog.tsx
index 660eb360..1752f503 100644
--- a/lib/pq/pq-criteria/add-pq-dialog.tsx
+++ b/lib/pq/pq-criteria/add-pq-dialog.tsx
@@ -38,6 +38,10 @@ import {
 
 import { useToast } from "@/hooks/use-toast"
 import { createPqCriteria } from "../service"
+import { uploadPqCriteriaFileAction } from "@/lib/pq/service"
+import { Dropzone, DropzoneInput, DropzoneZone, DropzoneUploadIcon, DropzoneTitle, DropzoneDescription } from "@/components/ui/dropzone"
+import { FileList, FileListHeader, FileListInfo, FileListItem, FileListName, FileListDescription, FileListAction } from "@/components/ui/file-list"
+import { X, Loader2 } from "lucide-react"
 
 // PQ 생성을 위한 Zod 스키마 정의
 const createPqSchema = z.object({
@@ -48,7 +52,7 @@ const createPqSchema = z.object({
   description: z.string().optional(),
   remarks: z.string().optional(),
   inputFormat: z.string().default("TEXT"),
-
+  type: z.string().optional(),
 });
 
 type CreatePqFormType = z.infer<typeof createPqSchema>;
@@ -74,6 +78,12 @@ const inputFormatOptions = [
   { value: "TEXT_FILE", label: "텍스트 + 파일" },
 ];
 
+const typeOptions = [
+  { value: "내자", label: "내자" },
+  { value: "외자", label: "외자" },
+  { value: "내외자", label: "내외자" },
+];
+
 interface AddPqDialogProps {
   pqListId: number;
 }
@@ -81,6 +91,10 @@ interface AddPqDialogProps {
 export function AddPqDialog({ pqListId }: AddPqDialogProps) {
   const [open, setOpen] = React.useState(false)
   const [isSubmitting, setIsSubmitting] = React.useState(false)
+  const [isUploading, setIsUploading] = React.useState(false)
+  const [uploadedFiles, setUploadedFiles] = React.useState<
+    { fileName: string; url: string; size?: number; originalFileName?: string }[]
+  >([])
   const router = useRouter()
   const { toast } = useToast()
 
@@ -95,7 +109,7 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
       description: "",
       remarks: "",
       inputFormat: "TEXT",
-
+      type: "내외자",
     },
   })
   const formState = form.formState
@@ -105,7 +119,10 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
       setIsSubmitting(true)
 
       // 서버 액션 호출
-      const result = await createPqCriteria(pqListId, data)
+      const result = await createPqCriteria(pqListId, {
+        ...data,
+        attachments: uploadedFiles,
+      })
 
       if (!result.success) {
         toast({
@@ -124,6 +141,7 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
 
       // 모달 닫고 폼 리셋
       form.reset()
+      setUploadedFiles([])
       setOpen(false)
 
       // 페이지 새로고침
@@ -144,10 +162,34 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
   function handleDialogOpenChange(nextOpen: boolean) {
     if (!nextOpen) {
       form.reset()
+      setUploadedFiles([])
     }
     setOpen(nextOpen)
   }
 
+  const handleUpload = async (files: File[]) => {
+    try {
+      setIsUploading(true)
+      for (const file of files) {
+        const uploaded = await uploadPqCriteriaFileAction(file)
+        setUploadedFiles((prev) => [...prev, uploaded])
+      }
+      toast({
+        title: "업로드 완료",
+        description: "첨부파일이 업로드되었습니다.",
+      })
+    } catch (error) {
+      console.error(error)
+      toast({
+        title: "업로드 실패",
+        description: "첨부파일 업로드 중 오류가 발생했습니다.",
+        variant: "destructive",
+      })
+    } finally {
+      setIsUploading(false)
+    }
+  }
+
   return (
     <Dialog open={open} onOpenChange={handleDialogOpenChange}>
       <DialogTrigger asChild>
@@ -253,6 +295,33 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
                 )}
               />
 
+              {/* Type 필드 */}
+              <FormField
+                control={form.control}
+                name="type"
+                render={({ field }) => (
+                  <FormItem>
+                    <FormLabel>내/외자 구분</FormLabel>
+                    <Select onValueChange={field.onChange} value={field.value}>
+                      <FormControl>
+                        <SelectTrigger>
+                          <SelectValue placeholder="구분을 선택하세요" />
+                        </SelectTrigger>
+                      </FormControl>
+                      <SelectContent>
+                        {typeOptions.map((option) => (
+                          <SelectItem key={option.value} value={option.value}>
+                            {option.label}
+                          </SelectItem>
+                        ))}
+                      </SelectContent>
+                    </Select>
+                    <FormDescription>미선택 시 기본값은 내외자입니다.</FormDescription>
+                    <FormMessage />
+                  </FormItem>
+                )}
+              />
+
               {/* Input Format 필드 */}
               <FormField
                 control={form.control}
@@ -279,6 +348,76 @@ export function AddPqDialog({ pqListId }: AddPqDialogProps) {
                 )}
               />
 
+              {/* 첨부 파일 업로드 */}
+              <div className="space-y-2">
+                <div className="flex items-center justify-between">
+                  <FormLabel>첨부 파일</FormLabel>
+                  {isUploading && (
+                    <div className="flex items-center text-xs text-muted-foreground">
+                      <Loader2 className="mr-1 h-3 w-3 animate-spin" /> 업로드 중...
+                    </div>
+                  )}
+                </div>
+                <Dropzone
+                  maxSize={6e8}
+                  onDropAccepted={(files) => handleUpload(files)}
+                  onDropRejected={() =>
+                    toast({
+                      title: "업로드 실패",
+                      description: "파일 크기/형식을 확인하세요.",
+                      variant: "destructive",
+                    })
+                  }
+                  disabled={isUploading}
+                >
+                  {() => (
+                    <FormItem>
+                      <DropzoneZone className="flex justify-center h-28">
+                        <FormControl>
+                          <DropzoneInput />
+                        </FormControl>
+                        <div className="flex items-center gap-4">
+                          <DropzoneUploadIcon />
+                          <div className="grid gap-0.5">
+                            <DropzoneTitle>파일을 드래그하거나 클릭하여 업로드</DropzoneTitle>
+                            <DropzoneDescription>PDF, 이미지, 문서 (최대 600MB)</DropzoneDescription>
+                          </div>
+                        </div>
+                      </DropzoneZone>
+                      <FormDescription>기준 문서 첨부가 필요한 경우 업로드하세요.</FormDescription>
+                    </FormItem>
+                  )}
+                </Dropzone>
+
+                {uploadedFiles.length > 0 && (
+                  <div className="space-y-2">
+                    <p className="text-sm font-medium">첨부된 파일 ({uploadedFiles.length})</p>
+                    <FileList>
+                      {uploadedFiles.map((file, idx) => (
+                        <FileListItem key={idx}>
+                          <FileListHeader>
+                            <FileListInfo>
+                              <FileListName>{file.originalFileName || file.fileName}</FileListName>
+                              {file.size && (
+                                <FileListDescription>{`${file.size} bytes`}</FileListDescription>
+                              )}
+                            </FileListInfo>
+                            <FileListAction
+                              onClick={() =>
+                                setUploadedFiles((prev) => prev.filter((_, i) => i !== idx))
+                              }
+                            >
+                              <X className="h-4 w-4" />
+                              <span className="sr-only">Remove</span>
+                            </FileListAction>
+                          </FileListHeader>
+                        </FileListItem>
+                      ))}
+                    </FileList>
+                  </div>
+                )}
+              </div>
+
               {/* Description 필드 */}
               <FormField
                 control={form.control}
-- 
cgit v1.2.3

