diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-29 11:33:37 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-09-29 11:33:37 +0000 |
| commit | 8438c05efc7a141e349c5d6416ad08156b4c0775 (patch) | |
| tree | d90080c294140db8082d0861c649845ec36c4cea /lib/rfq-last/vendor-response/editor/attachments-upload.tsx | |
| parent | c17b495c700dcfa040abc93a210727cbe72785f1 (diff) | |
(최겸) 구매 견적 이메일 추가, 미리보기, 첨부삭제, 기타 수정 등
Diffstat (limited to 'lib/rfq-last/vendor-response/editor/attachments-upload.tsx')
| -rw-r--r-- | lib/rfq-last/vendor-response/editor/attachments-upload.tsx | 134 |
1 files changed, 123 insertions, 11 deletions
diff --git a/lib/rfq-last/vendor-response/editor/attachments-upload.tsx b/lib/rfq-last/vendor-response/editor/attachments-upload.tsx index a2967767..ea7bb9c9 100644 --- a/lib/rfq-last/vendor-response/editor/attachments-upload.tsx +++ b/lib/rfq-last/vendor-response/editor/attachments-upload.tsx @@ -1,11 +1,20 @@ "use client" import { useState, useRef } from "react" +import { useSession } from "next-auth/react" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Alert, AlertDescription } from "@/components/ui/alert" import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +import { Table, TableBody, TableCell, @@ -23,10 +32,13 @@ import { Paperclip, FileCheck, Calculator, - Wrench + Wrench, + X } from "lucide-react" import { formatBytes } from "@/lib/utils" import { cn } from "@/lib/utils" +import { toast } from "sonner" +import { deleteVendorResponseAttachment } from "../../service" interface FileWithType extends File { attachmentType?: "구매" | "설계" @@ -37,6 +49,9 @@ interface AttachmentsUploadProps { attachments: FileWithType[] onAttachmentsChange: (files: FileWithType[]) => void existingAttachments?: any[] + onExistingAttachmentsChange?: (files: any[]) => void + responseId?: number + userId?: number } const acceptedFileTypes = { @@ -49,13 +64,18 @@ const acceptedFileTypes = { export default function AttachmentsUpload({ attachments, onAttachmentsChange, - existingAttachments = [] + existingAttachments = [], + onExistingAttachmentsChange, + responseId, + userId }: AttachmentsUploadProps) { const purchaseInputRef = useRef<HTMLInputElement>(null) const designInputRef = useRef<HTMLInputElement>(null) const [purchaseDragActive, setPurchaseDragActive] = useState(false) const [designDragActive, setDesignDragActive] = useState(false) const [uploadErrors, setUploadErrors] = useState<string[]>([]) + const [deleteDialogOpen, setDeleteDialogOpen] = useState(false) + const [fileToDelete, setFileToDelete] = useState<{file: any, isExisting: boolean, index: number} | null>(null) // 파일 유효성 검사 const validateFile = (file: File): string | null => { @@ -158,6 +178,57 @@ export default function AttachmentsUpload({ newFiles[index].attachmentType = newType onAttachmentsChange(newFiles) } + + // 파일 삭제 확인 + const handleDeleteClick = (file: any, isExisting: boolean, index: number) => { + setFileToDelete({ file, isExisting, index }) + setDeleteDialogOpen(true) + } + + // 파일 삭제 실행 + const handleDeleteConfirm = async () => { + if (!fileToDelete) return + + const { isExisting, index } = fileToDelete + + if (isExisting) { + // 기존 첨부파일 삭제 - 서버액션 호출 + if (responseId && userId && fileToDelete.file.id) { + try { + const result = await deleteVendorResponseAttachment({ + attachmentId: fileToDelete.file.id, + responseId, + userId + }) + if (result.success) { + // 클라이언트 상태 업데이트 + const newExistingAttachments = existingAttachments.filter((_, i) => i !== index) + onExistingAttachmentsChange?.(newExistingAttachments) + } else { + toast.error(`삭제 실패: ${result.error}`) + return + } + } catch (error) { + console.error('삭제 API 호출 실패:', error) + toast.error('삭제 중 오류가 발생했습니다.') + return + } + } + } else { + // 새 첨부파일 삭제 (클라이언트에서만) + const newFiles = attachments.filter((_, i) => i !== index) + onAttachmentsChange(newFiles) + } + + setDeleteDialogOpen(false) + setFileToDelete(null) + } + + // 파일 삭제 취소 + const handleDeleteCancel = () => { + setDeleteDialogOpen(false) + setFileToDelete(null) + } // 파일 아이콘 가져오기 const getFileIcon = (fileName: string) => { @@ -388,14 +459,24 @@ export default function AttachmentsUpload({ </Badge> </TableCell> <TableCell> - <Button - type="button" - variant="ghost" - size="sm" - onClick={() => window.open(file.filePath, '_blank')} - > - <Download className="h-4 w-4" /> - </Button> + <div className="flex items-center gap-1"> + <Button + type="button" + variant="ghost" + size="sm" + onClick={() => window.open(file.filePath, '_blank')} + > + <Download className="h-4 w-4" /> + </Button> + <Button + type="button" + variant="ghost" + size="sm" + onClick={() => handleDeleteClick(file, true, index)} + > + <Trash2 className="h-4 w-4 text-red-500" /> + </Button> + </div> </TableCell> </TableRow> ))} @@ -449,7 +530,7 @@ export default function AttachmentsUpload({ type="button" variant="ghost" size="sm" - onClick={() => handleFileRemove(index)} + onClick={() => handleDeleteClick(file, false, index)} > <Trash2 className="h-4 w-4 text-red-500" /> </Button> @@ -461,6 +542,37 @@ export default function AttachmentsUpload({ </CardContent> </Card> )} + + {/* 파일 삭제 확인 다이얼로그 */} + <Dialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}> + <DialogContent> + <DialogHeader> + <DialogTitle>파일 삭제</DialogTitle> + <DialogDescription> + {fileToDelete?.isExisting ? '기존 첨부파일' : '새로 업로드한 파일'} "{fileToDelete?.file.originalFileName || fileToDelete?.file.name}"을(를) 삭제하시겠습니까? + <br /> + <strong>삭제된 파일은 복구할 수 없습니다.</strong> + </DialogDescription> + </DialogHeader> + <DialogFooter> + <Button + type="button" + variant="outline" + onClick={handleDeleteCancel} + > + 취소 + </Button> + <Button + type="button" + variant="destructive" + onClick={handleDeleteConfirm} + > + <Trash2 className="h-4 w-4 mr-2" /> + 삭제 + </Button> + </DialogFooter> + </DialogContent> + </Dialog> </div> ) }
\ No newline at end of file |
