summaryrefslogtreecommitdiff
path: root/lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx')
-rw-r--r--lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx183
1 files changed, 93 insertions, 90 deletions
diff --git a/lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx b/lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx
index ecdf6d81..a7b487e1 100644
--- a/lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx
+++ b/lib/techsales-rfq/table/tech-sales-rfq-attachments-sheet.tsx
@@ -27,7 +27,6 @@ import {
import { Loader, Download, X, Eye, AlertCircle } from "lucide-react"
import { toast } from "sonner"
import { Badge } from "@/components/ui/badge"
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import {
Dropzone,
@@ -63,7 +62,7 @@ export interface ExistingTechSalesAttachment {
filePath: string
fileSize?: number
fileType?: string
- attachmentType: "RFQ_COMMON" | "VENDOR_SPECIFIC"
+ attachmentType: "RFQ_COMMON" | "TBE_RESULT" | "CBE_RESULT"
description?: string
createdBy: number
createdAt: Date
@@ -72,7 +71,7 @@ export interface ExistingTechSalesAttachment {
/** 새로 업로드할 파일 */
const newUploadSchema = z.object({
fileObj: z.any().optional(), // 실제 File
- attachmentType: z.enum(["RFQ_COMMON", "VENDOR_SPECIFIC"]).default("RFQ_COMMON"),
+ attachmentType: z.enum(["RFQ_COMMON", "TBE_RESULT", "CBE_RESULT"]).default("RFQ_COMMON"),
description: z.string().optional(),
})
@@ -85,7 +84,7 @@ const existingAttachSchema = z.object({
filePath: z.string(),
fileSize: z.number().optional(),
fileType: z.string().optional(),
- attachmentType: z.enum(["RFQ_COMMON", "VENDOR_SPECIFIC"]),
+ attachmentType: z.enum(["RFQ_COMMON", "TBE_RESULT", "CBE_RESULT"]),
description: z.string().optional(),
createdBy: z.number(),
createdAt: z.custom<Date>(),
@@ -112,27 +111,54 @@ interface TechSalesRfqAttachmentsSheetProps
extends React.ComponentPropsWithRef<typeof Sheet> {
defaultAttachments?: ExistingTechSalesAttachment[]
rfq: TechSalesRfq | null
+ /** 첨부파일 타입 */
+ attachmentType?: "RFQ_COMMON" | "TBE_RESULT" | "CBE_RESULT"
/** 업로드/삭제 후 상위 테이블에 attachmentCount 등을 업데이트하기 위한 콜백 */
- onAttachmentsUpdated?: (rfqId: number, newAttachmentCount: number) => void
- /** 강제 읽기 전용 모드 (파트너/벤더용) */
- readOnly?: boolean
+ // onAttachmentsUpdated?: (rfqId: number, newAttachmentCount: number) => void
+
}
export function TechSalesRfqAttachmentsSheet({
defaultAttachments = [],
- onAttachmentsUpdated,
+ // onAttachmentsUpdated,
rfq,
- readOnly = false,
+ attachmentType = "RFQ_COMMON",
...props
}: TechSalesRfqAttachmentsSheetProps) {
const [isPending, setIsPending] = React.useState(false)
- // RFQ 상태에 따른 편집 가능 여부 결정 (readOnly prop이 true면 항상 false)
- const isEditable = React.useMemo(() => {
- if (!rfq || readOnly) return false
- // RFQ Created, RFQ Vendor Assignned 상태에서만 편집 가능
- return ["RFQ Created", "RFQ Vendor Assignned"].includes(rfq.status)
- }, [rfq, readOnly])
+ // 첨부파일 타입별 제목과 설명 설정
+ const attachmentConfig = React.useMemo(() => {
+ switch (attachmentType) {
+ case "TBE_RESULT":
+ return {
+ title: "TBE 결과 첨부파일",
+ description: "기술 평가(TBE) 결과 파일을 관리합니다.",
+ fileTypeLabel: "TBE 결과",
+ canEdit: true
+ }
+ case "CBE_RESULT":
+ return {
+ title: "CBE 결과 첨부파일",
+ description: "상업성 평가(CBE) 결과 파일을 관리합니다.",
+ fileTypeLabel: "CBE 결과",
+ canEdit: true
+ }
+ default: // RFQ_COMMON
+ return {
+ title: "RFQ 첨부파일",
+ description: "RFQ 공통 첨부파일을 관리합니다.",
+ fileTypeLabel: "공통",
+ canEdit: true
+ }
+ }
+ }, [attachmentType, rfq?.status])
+
+ // // RFQ 상태에 따른 편집 가능 여부 결정 (readOnly prop이 true면 항상 false)
+ // const isEditable = React.useMemo(() => {
+ // if (!rfq) return false
+ // return attachmentConfig.canEdit
+ // }, [rfq, attachmentConfig.canEdit])
const form = useForm<AttachmentsFormValues>({
resolver: zodResolver(attachmentsFormSchema),
@@ -236,7 +262,7 @@ export function TechSalesRfqAttachmentsSheet({
.filter(upload => upload.fileObj)
.map(upload => ({
file: upload.fileObj as File,
- attachmentType: upload.attachmentType,
+ attachmentType: attachmentType,
description: upload.description,
}))
@@ -268,50 +294,50 @@ export function TechSalesRfqAttachmentsSheet({
toast.success(successMessage)
- // 즉시 첨부파일 목록 새로고침
- const refreshResult = await getTechSalesRfqAttachments(rfq.id)
- if (refreshResult.error) {
- console.error("첨부파일 목록 새로고침 실패:", refreshResult.error)
- toast.warning("첨부파일 목록 새로고침에 실패했습니다. 시트를 다시 열어주세요.")
- } else {
- // 새로운 첨부파일 목록으로 폼 업데이트
- const refreshedAttachments = refreshResult.data.map(att => ({
- id: att.id,
- techSalesRfqId: att.techSalesRfqId || rfq.id,
- fileName: att.fileName,
- originalFileName: att.originalFileName,
- filePath: att.filePath,
- fileSize: att.fileSize,
- fileType: att.fileType,
- attachmentType: att.attachmentType as "RFQ_COMMON" | "VENDOR_SPECIFIC",
- description: att.description,
- createdBy: att.createdBy,
- createdAt: att.createdAt,
- }))
-
- // 폼을 새로운 데이터로 리셋 (새 업로드 목록은 비움)
- form.reset({
- techSalesRfqId: rfq.id,
- existing: refreshedAttachments.map(att => ({
- ...att,
- fileSize: att.fileSize || undefined,
- fileType: att.fileType || undefined,
- description: att.description || undefined,
- })),
- newUploads: [],
- })
+ // // 즉시 첨부파일 목록 새로고침
+ // const refreshResult = await getTechSalesRfqAttachments(rfq.id)
+ // if (refreshResult.error) {
+ // console.error("첨부파일 목록 새로고침 실패:", refreshResult.error)
+ // toast.warning("첨부파일 목록 새로고침에 실패했습니다. 시트를 다시 열어주세요.")
+ // } else {
+ // // 새로운 첨부파일 목록으로 폼 업데이트
+ // const refreshedAttachments = refreshResult.data.map(att => ({
+ // id: att.id,
+ // techSalesRfqId: att.techSalesRfqId || rfq.id,
+ // fileName: att.fileName,
+ // originalFileName: att.originalFileName,
+ // filePath: att.filePath,
+ // fileSize: att.fileSize,
+ // fileType: att.fileType,
+ // attachmentType: att.attachmentType as "RFQ_COMMON" | "TBE_RESULT" | "CBE_RESULT",
+ // description: att.description,
+ // createdBy: att.createdBy,
+ // createdAt: att.createdAt,
+ // }))
+
+ // // 폼을 새로운 데이터로 리셋 (새 업로드 목록은 비움)
+ // form.reset({
+ // techSalesRfqId: rfq.id,
+ // existing: refreshedAttachments.map(att => ({
+ // ...att,
+ // fileSize: att.fileSize || undefined,
+ // fileType: att.fileType || undefined,
+ // description: att.description || undefined,
+ // })),
+ // newUploads: [],
+ // })
- // 즉시 UI 업데이트를 위한 추가 피드백
- if (uploadedCount > 0) {
- toast.success("첨부파일 목록이 업데이트되었습니다.", { duration: 2000 })
- }
- }
+ // // 즉시 UI 업데이트를 위한 추가 피드백
+ // if (uploadedCount > 0) {
+ // toast.success("첨부파일 목록이 업데이트되었습니다.", { duration: 2000 })
+ // }
+ // }
- // 콜백으로 상위 컴포넌트에 변경사항 알림
- const newAttachmentCount = refreshResult.error ?
- (data.existing.length + newFiles.length - deleteAttachmentIds.length) :
- refreshResult.data.length
- onAttachmentsUpdated?.(rfq.id, newAttachmentCount)
+ // // 콜백으로 상위 컴포넌트에 변경사항 알림
+ // const newAttachmentCount = refreshResult.error ?
+ // (data.existing.length + newFiles.length - deleteAttachmentIds.length) :
+ // refreshResult.data.length
+ // onAttachmentsUpdated?.(rfq.id, newAttachmentCount)
} catch (error) {
console.error("첨부파일 저장 오류:", error)
@@ -325,10 +351,11 @@ export function TechSalesRfqAttachmentsSheet({
<Sheet {...props}>
<SheetContent className="flex flex-col gap-6 sm:max-w-md">
<SheetHeader className="text-left">
- <SheetTitle>첨부파일 관리</SheetTitle>
+ <SheetTitle>{attachmentConfig.title}</SheetTitle>
<SheetDescription>
- RFQ: {rfq?.rfqCode || "N/A"}
- {!isEditable && (
+ <div>RFQ: {rfq?.rfqCode || "N/A"}</div>
+ <div className="mt-1">{attachmentConfig.description}</div>
+ {!attachmentConfig.canEdit && (
<div className="mt-2 flex items-center gap-2 text-amber-600">
<AlertCircle className="h-4 w-4" />
<span className="text-sm">현재 상태에서는 편집할 수 없습니다</span>
@@ -345,7 +372,7 @@ export function TechSalesRfqAttachmentsSheet({
기존 첨부파일 ({existingFields.length}개)
</h6>
{existingFields.map((field, index) => {
- const typeLabel = field.attachmentType === "RFQ_COMMON" ? "공통" : "벤더별"
+ const typeLabel = attachmentConfig.fileTypeLabel
const sizeText = field.fileSize ? prettyBytes(field.fileSize) : "알 수 없음"
const dateText = field.createdAt ? formatDate(field.createdAt) : ""
@@ -384,7 +411,7 @@ export function TechSalesRfqAttachmentsSheet({
</a>
)}
{/* Remove button - 편집 가능할 때만 표시 */}
- {isEditable && (
+ {attachmentConfig.canEdit && (
<Button
type="button"
variant="ghost"
@@ -402,7 +429,7 @@ export function TechSalesRfqAttachmentsSheet({
</div>
{/* 2) Dropzone for new uploads - 편집 가능할 때만 표시 */}
- {isEditable ? (
+ {attachmentConfig.canEdit ? (
<>
<Dropzone
maxSize={MAX_FILE_SIZE}
@@ -467,30 +494,6 @@ export function TechSalesRfqAttachmentsSheet({
</FileListAction>
</FileListHeader>
- {/* 파일별 설정 */}
- <div className="px-4 pb-3 space-y-3">
- <FormField
- control={form.control}
- name={`newUploads.${idx}.attachmentType`}
- render={({ field: formField }) => (
- <FormItem>
- <FormLabel className="text-xs">파일 타입</FormLabel>
- <Select onValueChange={formField.onChange} defaultValue={formField.value}>
- <FormControl>
- <SelectTrigger className="h-8">
- <SelectValue placeholder="파일 타입 선택" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- <SelectItem value="RFQ_COMMON">공통 파일</SelectItem>
- {/* <SelectItem value="VENDOR_SPECIFIC">벤더별 파일</SelectItem> */}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
- </div>
</FileListItem>
)
})}
@@ -510,10 +513,10 @@ export function TechSalesRfqAttachmentsSheet({
<SheetFooter className="gap-2 pt-2 sm:space-x-0">
<SheetClose asChild>
<Button type="button" variant="outline">
- {isEditable ? "취소" : "닫기"}
+ {attachmentConfig.canEdit ? "취소" : "닫기"}
</Button>
</SheetClose>
- {isEditable && (
+ {attachmentConfig.canEdit && (
<Button
type="submit"
disabled={