summaryrefslogtreecommitdiff
path: root/lib/b-rfq/attachment/add-revision-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/b-rfq/attachment/add-revision-dialog.tsx')
-rw-r--r--lib/b-rfq/attachment/add-revision-dialog.tsx336
1 files changed, 0 insertions, 336 deletions
diff --git a/lib/b-rfq/attachment/add-revision-dialog.tsx b/lib/b-rfq/attachment/add-revision-dialog.tsx
deleted file mode 100644
index 1abefb02..00000000
--- a/lib/b-rfq/attachment/add-revision-dialog.tsx
+++ /dev/null
@@ -1,336 +0,0 @@
-"use client"
-
-import * as React from "react"
-import { useForm } from "react-hook-form"
-import { zodResolver } from "@hookform/resolvers/zod"
-import { z } from "zod"
-import { Upload } from "lucide-react"
-import { toast } from "sonner"
-
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
-} from "@/components/ui/dialog"
-import {
- Form,
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from "@/components/ui/form"
-import {
- Dropzone,
- DropzoneDescription,
- DropzoneInput,
- DropzoneTitle,
- DropzoneUploadIcon,
- DropzoneZone,
-} from "@/components/ui/dropzone"
-import {
- FileList,
- FileListAction,
- FileListDescription,
- FileListHeader,
- FileListIcon,
- FileListInfo,
- FileListItem,
- FileListName,
- FileListSize,
-} from "@/components/ui/file-list"
-import { Button } from "@/components/ui/button"
-import { Textarea } from "@/components/ui/textarea"
-import { addRevisionToAttachment } from "../service"
-
-// 리비전 추가 폼 스키마
-const addRevisionSchema = z.object({
- revisionComment: z.string().optional(),
- file: z.instanceof(File, {
- message: "파일을 선택해주세요.",
- }),
-})
-
-type AddRevisionFormData = z.infer<typeof addRevisionSchema>
-
-interface AddRevisionDialogProps {
- open: boolean
- onOpenChange: (open: boolean) => void
- attachmentId: number
- currentRevision: string
- originalFileName: string
- onSuccess?: () => void
-}
-
-export function AddRevisionDialog({
- open,
- onOpenChange,
- attachmentId,
- currentRevision,
- originalFileName,
- onSuccess
-}: AddRevisionDialogProps) {
- const [isSubmitting, setIsSubmitting] = React.useState(false)
- const [uploadProgress, setUploadProgress] = React.useState<number>(0)
-
- const form = useForm<AddRevisionFormData>({
- resolver: zodResolver(addRevisionSchema),
- defaultValues: {
- revisionComment: "",
- file: undefined,
- },
- })
-
- const selectedFile = form.watch("file")
-
- // 다이얼로그 닫기 핸들러
- const handleOpenChange = (newOpen: boolean) => {
- if (!newOpen && !isSubmitting) {
- form.reset()
- }
- onOpenChange(newOpen)
- }
-
- // 파일 선택 처리
- const handleFileChange = (files: File[]) => {
- if (files.length === 0) return
-
- const file = files[0]
-
- // 파일 크기 검증
- const maxFileSize = 10 * 1024 * 1024 // 10MB
- if (file.size > maxFileSize) {
- toast.error(`파일이 너무 큽니다. (최대 10MB)`)
- return
- }
-
- form.setValue("file", file)
- form.clearErrors("file")
- }
-
- // 파일 제거
- const removeFile = () => {
- form.resetField("file")
- }
-
- // 파일 업로드 API 호출
- const uploadFile = async (file: File): Promise<{
- fileName: string
- originalFileName: string
- filePath: string
- fileSize: number
- fileType: string
- }> => {
- const formData = new FormData()
- formData.append("attachmentId", attachmentId.toString())
- formData.append("file", file)
- formData.append("isRevision", "true")
-
- const response = await fetch("/api/upload/rfq-attachment-revision", {
- method: "POST",
- body: formData,
- })
-
- if (!response.ok) {
- const error = await response.json()
- throw new Error(error.message || "파일 업로드 실패")
- }
-
- return response.json()
- }
-
- // 폼 제출
- const onSubmit = async (data: AddRevisionFormData) => {
- setIsSubmitting(true)
- setUploadProgress(0)
-
- try {
- // 1단계: 파일 업로드
- setUploadProgress(30)
- const uploadedFile = await uploadFile(data.file)
-
- // 2단계: DB 리비전 레코드 생성
- setUploadProgress(70)
- const result = await addRevisionToAttachment(attachmentId, {
- fileName: uploadedFile.fileName,
- originalFileName: uploadedFile.originalFileName,
- filePath: uploadedFile.filePath,
- fileSize: uploadedFile.fileSize,
- fileType: uploadedFile.fileType,
- revisionComment: data.revisionComment,
- })
-
- setUploadProgress(100)
-
- if (result.success) {
- toast.success(result.message)
- form.reset()
- handleOpenChange(false)
- onSuccess?.()
- } else {
- toast.error(result.message)
- }
-
- } catch (error) {
- console.error("Upload error:", error)
- toast.error(error instanceof Error ? error.message : "리비전 추가 중 오류가 발생했습니다.")
- } finally {
- setIsSubmitting(false)
- setUploadProgress(0)
- }
- }
-
- // 다음 리비전 번호 계산
- const getNextRevision = (current: string) => {
- const match = current.match(/Rev\.(\d+)/)
- if (match) {
- const num = parseInt(match[1]) + 1
- return `Rev.${num}`
- }
- return "Rev.1"
- }
-
- const nextRevision = getNextRevision(currentRevision)
-
- return (
- <Dialog open={open} onOpenChange={handleOpenChange}>
- <DialogContent className="sm:max-w-[500px]">
- <DialogHeader>
- <DialogTitle className="flex items-center gap-2">
- <Upload className="h-5 w-5" />
- 새 리비전 추가
- </DialogTitle>
- <DialogDescription>
- "{originalFileName}"의 새 버전을 업로드합니다.
- 현재 {currentRevision} → {nextRevision}
- </DialogDescription>
- </DialogHeader>
-
- <Form {...form}>
- <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
- {/* 리비전 코멘트 */}
- <FormField
- control={form.control}
- name="revisionComment"
- render={({ field }) => (
- <FormItem>
- <FormLabel>리비전 코멘트 (선택)</FormLabel>
- <FormControl>
- <Textarea
- placeholder={`${nextRevision} 업데이트 내용을 입력하세요`}
- className="resize-none"
- rows={3}
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- {/* 파일 선택 - Dropzone (단일 파일) */}
- <FormField
- control={form.control}
- name="file"
- render={({ field }) => (
- <FormItem>
- <FormLabel>새 파일 선택</FormLabel>
- <FormControl>
- <div className="space-y-3">
- <Dropzone
- onDrop={(acceptedFiles) => {
- handleFileChange(acceptedFiles)
- }}
- 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'],
- 'application/vnd.ms-powerpoint': ['.ppt'],
- 'application/vnd.openxmlformats-officedocument.presentationml.presentation': ['.pptx'],
- 'application/zip': ['.zip'],
- 'application/x-rar-compressed': ['.rar']
- }}
- maxSize={10 * 1024 * 1024} // 10MB
- multiple={false}
- disabled={isSubmitting}
- >
- <DropzoneZone>
- <DropzoneUploadIcon />
- <DropzoneTitle>클릭하여 파일 선택 또는 드래그 앤 드롭</DropzoneTitle>
- <DropzoneDescription>
- PDF, DOC, XLS, PPT 등 (최대 10MB, 파일 1개)
- </DropzoneDescription>
- <DropzoneInput />
- </DropzoneZone>
- </Dropzone>
-
- {/* 선택된 파일 표시 */}
- {selectedFile && (
- <div className="space-y-2">
- <FileListHeader>
- 선택된 파일 ({nextRevision})
- </FileListHeader>
- <FileList>
- <FileListItem>
- <FileListIcon />
- <FileListInfo>
- <FileListName>{selectedFile.name}</FileListName>
- <FileListDescription>
- <FileListSize>{selectedFile.size}</FileListSize>
- </FileListDescription>
- </FileListInfo>
- <FileListAction
- onClick={removeFile}
- disabled={isSubmitting}
- />
- </FileListItem>
- </FileList>
- </div>
- )}
-
- {/* 업로드 진행률 */}
- {isSubmitting && uploadProgress > 0 && (
- <div className="space-y-2">
- <div className="flex justify-between text-sm">
- <span>업로드 진행률</span>
- <span>{uploadProgress}%</span>
- </div>
- <div className="w-full bg-gray-200 rounded-full h-2">
- <div
- className="bg-blue-600 h-2 rounded-full transition-all duration-300"
- style={{ width: `${uploadProgress}%` }}
- />
- </div>
- </div>
- )}
- </div>
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
-
- <DialogFooter>
- <Button
- type="button"
- variant="outline"
- onClick={() => handleOpenChange(false)}
- disabled={isSubmitting}
- >
- 취소
- </Button>
- <Button type="submit" disabled={isSubmitting || !selectedFile}>
- {isSubmitting ? "업로드 중..." : `${nextRevision} 추가`}
- </Button>
- </DialogFooter>
- </form>
- </Form>
- </DialogContent>
- </Dialog>
- )
-} \ No newline at end of file