From 1eb7cf92d1d7711e5d62a750e7611dc6fd1a241d Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Fri, 28 Nov 2025 07:45:32 +0000
Subject: (최겸) 구매 피드백 반영(입찰SAP 취소 개발 잔재)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 lib/bidding/selection/selection-result-form.tsx | 98 +++++++++++++++++--------
 1 file changed, 67 insertions(+), 31 deletions(-)

(limited to 'lib/bidding/selection/selection-result-form.tsx')

diff --git a/lib/bidding/selection/selection-result-form.tsx b/lib/bidding/selection/selection-result-form.tsx
index 7f1229a2..54687cc9 100644
--- a/lib/bidding/selection/selection-result-form.tsx
+++ b/lib/bidding/selection/selection-result-form.tsx
@@ -8,14 +8,13 @@ import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
 import { Button } from '@/components/ui/button'
 import { Textarea } from '@/components/ui/textarea'
 import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'
-import { FileUpload } from '@/components/ui/file-upload'
 import { useToast } from '@/hooks/use-toast'
 import { saveSelectionResult } from './actions'
-import { Loader2, Save } from 'lucide-react'
+import { Loader2, Save, FileText } from 'lucide-react'
+import { Dropzone, DropzoneZone, DropzoneUploadIcon, DropzoneTitle, DropzoneDescription, DropzoneInput } from '@/components/ui/dropzone'
 
 const selectionResultSchema = z.object({
   summary: z.string().min(1, '결과요약을 입력해주세요'),
-  attachments: z.array(z.any()).optional(),
 })
 
 type SelectionResultFormData = z.infer<typeof selectionResultSchema>
@@ -28,22 +27,26 @@ interface SelectionResultFormProps {
 export function SelectionResultForm({ biddingId, onSuccess }: SelectionResultFormProps) {
   const { toast } = useToast()
   const [isSubmitting, setIsSubmitting] = React.useState(false)
+  const [attachmentFiles, setAttachmentFiles] = React.useState<File[]>([])
 
   const form = useForm<SelectionResultFormData>({
     resolver: zodResolver(selectionResultSchema),
     defaultValues: {
       summary: '',
-      attachments: [],
     },
   })
 
+  const removeAttachmentFile = (index: number) => {
+    setAttachmentFiles(prev => prev.filter((_, i) => i !== index))
+  }
+
   const onSubmit = async (data: SelectionResultFormData) => {
     setIsSubmitting(true)
     try {
       const result = await saveSelectionResult({
         biddingId,
         summary: data.summary,
-        attachments: data.attachments
+        attachments: attachmentFiles
       })
 
       if (result.success) {
@@ -99,33 +102,66 @@ export function SelectionResultForm({ biddingId, onSuccess }: SelectionResultFor
             />
 
             {/* 첨부파일 */}
-            <FormField
-              control={form.control}
-              name="attachments"
-              render={({ field }) => (
-                <FormItem>
-                  <FormLabel>첨부파일</FormLabel>
-                  <FormControl>
-                    <FileUpload
-                      value={field.value || []}
-                      onChange={field.onChange}
-                      accept={{
-                        'application/pdf': ['.pdf'],
-                        'application/msword': ['.doc'],
-                        'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
-                        'application/vnd.ms-excel': ['.xls'],
-                        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx'],
-                        'image/*': ['.png', '.jpg', '.jpeg', '.gif'],
-                      }}
-                      maxSize={10 * 1024 * 1024} // 10MB
-                      maxFiles={5}
-                      placeholder="선정결과 관련 문서를 업로드해주세요"
-                    />
-                  </FormControl>
-                  <FormMessage />
-                </FormItem>
+            <div className="space-y-4">
+              <FormLabel>첨부파일</FormLabel>
+              <Dropzone
+                maxSize={10 * 1024 * 1024} // 10MB
+                onDropAccepted={(files) => {
+                  const newFiles = Array.from(files)
+                  setAttachmentFiles(prev => [...prev, ...newFiles])
+                }}
+                onDropRejected={() => {
+                  toast({
+                    title: "파일 업로드 거부",
+                    description: "파일 크기 및 형식을 확인해주세요.",
+                    variant: "destructive",
+                  })
+                }}
+              >
+                <DropzoneZone>
+                  <DropzoneUploadIcon className="mx-auto h-12 w-12 text-muted-foreground" />
+                  <DropzoneTitle className="text-lg font-medium">
+                    파일을 드래그하거나 클릭하여 업로드
+                  </DropzoneTitle>
+                  <DropzoneDescription className="text-sm text-muted-foreground">
+                    PDF, Word, Excel, 이미지 파일 (최대 10MB)
+                  </DropzoneDescription>
+                </DropzoneZone>
+                <DropzoneInput />
+              </Dropzone>
+
+              {attachmentFiles.length > 0 && (
+                <div className="space-y-2">
+                  <h4 className="text-sm font-medium">업로드된 파일</h4>
+                  <div className="space-y-2">
+                    {attachmentFiles.map((file, index) => (
+                      <div
+                        key={index}
+                        className="flex items-center justify-between p-3 bg-muted rounded-lg"
+                      >
+                        <div className="flex items-center gap-3">
+                          <FileText className="h-4 w-4 text-muted-foreground" />
+                          <div>
+                            <p className="text-sm font-medium">{file.name}</p>
+                            <p className="text-xs text-muted-foreground">
+                              {(file.size / 1024 / 1024).toFixed(2)} MB
+                            </p>
+                          </div>
+                        </div>
+                        <Button
+                          type="button"
+                          variant="ghost"
+                          size="sm"
+                          onClick={() => removeAttachmentFile(index)}
+                        >
+                          제거
+                        </Button>
+                      </div>
+                    ))}
+                  </div>
+                </div>
               )}
-            />
+            </div>
 
             {/* 저장 버튼 */}
             <div className="flex justify-end">
-- 
cgit v1.2.3

