summaryrefslogtreecommitdiff
path: root/lib/b-rfq/vendor-response/response-detail-sheet.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-12-01 19:52:06 +0900
committerjoonhoekim <26rote@gmail.com>2025-12-01 19:52:06 +0900
commit44b74ff4170090673b6eeacd8c528e0abf47b7aa (patch)
tree3f3824b4e2cb24536c1677188b4cae5b8909d3da /lib/b-rfq/vendor-response/response-detail-sheet.tsx
parent4953e770929b82ef77da074f77071ebd0f428529 (diff)
(김준회) deprecated code 정리
Diffstat (limited to 'lib/b-rfq/vendor-response/response-detail-sheet.tsx')
-rw-r--r--lib/b-rfq/vendor-response/response-detail-sheet.tsx358
1 files changed, 0 insertions, 358 deletions
diff --git a/lib/b-rfq/vendor-response/response-detail-sheet.tsx b/lib/b-rfq/vendor-response/response-detail-sheet.tsx
deleted file mode 100644
index da7f9b01..00000000
--- a/lib/b-rfq/vendor-response/response-detail-sheet.tsx
+++ /dev/null
@@ -1,358 +0,0 @@
-// components/rfq/response-detail-sheet.tsx
-"use client";
-
-import { Button } from "@/components/ui/button";
-import { Badge } from "@/components/ui/badge";
-import {
- Sheet,
- SheetContent,
- SheetDescription,
- SheetHeader,
- SheetTitle,
- SheetTrigger,
-} from "@/components/ui/sheet";
-import {
- FileText,
- Upload,
- Download,
- AlertCircle,
- MessageSquare,
- FileCheck,
- Eye
-} from "lucide-react";
-import { formatDateTime, formatFileSize } from "@/lib/utils";
-import { cn } from "@/lib/utils";
-import type { EnhancedVendorResponse } from "@/lib/b-rfq/service";
-
-// 파일 다운로드 핸들러 (API 사용)
-async function handleFileDownload(
- filePath: string,
- fileName: string,
- type: "client" | "vendor" = "client",
- id?: number
-) {
- try {
- const params = new URLSearchParams({
- path: filePath,
- type: type,
- });
-
- // ID가 있으면 추가
- if (id) {
- if (type === "client") {
- params.append("revisionId", id.toString());
- } else {
- params.append("responseFileId", id.toString());
- }
- }
-
- const response = await fetch(`/api/rfq-attachments/download?${params.toString()}`);
-
- if (!response.ok) {
- const errorData = await response.json();
- throw new Error(errorData.error || `Download failed: ${response.status}`);
- }
-
- // Blob으로 파일 데이터 받기
- const blob = await response.blob();
-
- // 임시 URL 생성하여 다운로드
- const url = window.URL.createObjectURL(blob);
- const link = document.createElement('a');
- link.href = url;
- link.download = fileName;
- document.body.appendChild(link);
- link.click();
-
- // 정리
- document.body.removeChild(link);
- window.URL.revokeObjectURL(url);
-
- console.log("✅ 파일 다운로드 성공:", fileName);
-
- } catch (error) {
- console.error("❌ 파일 다운로드 실패:", error);
-
- // 사용자에게 에러 알림 (토스트나 알럿으로 대체 가능)
- alert(`파일 다운로드에 실패했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'}`);
- }
-}
-
-// 효과적인 상태별 아이콘 및 색상
-function getEffectiveStatusInfo(effectiveStatus: string) {
- switch (effectiveStatus) {
- case "NOT_RESPONDED":
- return {
- label: "미응답",
- variant: "outline" as const
- };
- case "UP_TO_DATE":
- return {
- label: "최신",
- variant: "default" as const
- };
- case "VERSION_MISMATCH":
- return {
- label: "업데이트 필요",
- variant: "secondary" as const
- };
- case "REVISION_REQUESTED":
- return {
- label: "수정요청",
- variant: "secondary" as const
- };
- case "WAIVED":
- return {
- label: "포기",
- variant: "outline" as const
- };
- default:
- return {
- label: effectiveStatus,
- variant: "outline" as const
- };
- }
-}
-
-interface ResponseDetailSheetProps {
- response: EnhancedVendorResponse;
- trigger?: React.ReactNode;
-}
-
-export function ResponseDetailSheet({ response, trigger }: ResponseDetailSheetProps) {
- const hasMultipleRevisions = response.attachment?.revisions && response.attachment.revisions.length > 1;
- const hasResponseFiles = response.responseAttachments && response.responseAttachments.length > 0;
-
- return (
- <Sheet>
- <SheetTrigger asChild>
- {trigger || (
- <Button size="sm" variant="ghost">
- <Eye className="h-3 w-3 mr-1" />
- 상세
- </Button>
- )}
- </SheetTrigger>
- <SheetContent side="right" className="w-[600px] sm:w-[800px] overflow-y-auto">
- <SheetHeader>
- <SheetTitle className="flex items-center gap-2">
- <FileText className="h-5 w-5" />
- 상세 정보 - {response.serialNo}
- </SheetTitle>
- <SheetDescription>
- {response.attachmentType} • {response.attachment?.revisions?.[0]?.originalFileName}
- </SheetDescription>
- </SheetHeader>
-
- <div className="space-y-6 mt-6">
- {/* 기본 정보 */}
- <div className="space-y-4">
- <h3 className="text-lg font-semibold flex items-center gap-2">
- <AlertCircle className="h-4 w-4" />
- 기본 정보
- </h3>
- <div className="grid grid-cols-2 gap-4 p-4 bg-muted/30 rounded-lg">
- <div>
- <div className="text-sm text-muted-foreground">상태</div>
- <div className="font-medium">{getEffectiveStatusInfo(response.effectiveStatus).label}</div>
- </div>
- <div>
- <div className="text-sm text-muted-foreground">현재 리비전</div>
- <div className="font-medium">{response.currentRevision}</div>
- </div>
- <div>
- <div className="text-sm text-muted-foreground">응답 리비전</div>
- <div className="font-medium">{response.respondedRevision || "-"}</div>
- </div>
- <div>
- <div className="text-sm text-muted-foreground">응답일</div>
- <div className="font-medium">
- {response.respondedAt ? formatDateTime(new Date(response.respondedAt)) : "-"}
- </div>
- </div>
- <div>
- <div className="text-sm text-muted-foreground">요청일</div>
- <div className="font-medium">
- {formatDateTime(new Date(response.requestedAt))}
- </div>
- </div>
- <div>
- <div className="text-sm text-muted-foreground">응답 파일 수</div>
- <div className="font-medium">{response.totalResponseFiles}개</div>
- </div>
- </div>
- </div>
-
- {/* 코멘트 정보 */}
- <div className="space-y-4">
- <h3 className="text-lg font-semibold flex items-center gap-2">
- <MessageSquare className="h-4 w-4" />
- 코멘트
- </h3>
- <div className="space-y-3">
- {response.responseComment && (
- <div className="p-3 border-l-4 border-blue-500 bg-blue-50">
- <div className="text-sm font-medium text-blue-700 mb-1">발주처 응답 코멘트</div>
- <div className="text-sm">{response.responseComment}</div>
- </div>
- )}
- {response.vendorComment && (
- <div className="p-3 border-l-4 border-green-500 bg-green-50">
- <div className="text-sm font-medium text-green-700 mb-1">내부 메모</div>
- <div className="text-sm">{response.vendorComment}</div>
- </div>
- )}
- {response.attachment?.revisions?.find(r => r.revisionComment) && (
- <div className="p-3 border-l-4 border-orange-500 bg-orange-50">
- <div className="text-sm font-medium text-orange-700 mb-1">발주처 요청 사항</div>
- <div className="text-sm">
- {response.attachment.revisions.find(r => r.revisionComment)?.revisionComment}
- </div>
- </div>
- )}
- {!response.responseComment && !response.vendorComment && !response.attachment?.revisions?.find(r => r.revisionComment) && (
- <div className="text-center text-muted-foreground py-4 bg-muted/20 rounded-lg">
- 코멘트가 없습니다.
- </div>
- )}
- </div>
- </div>
-
- {/* 발주처 리비전 히스토리 */}
- {hasMultipleRevisions && (
- <div className="space-y-4">
- <h3 className="text-lg font-semibold flex items-center gap-2">
- <FileCheck className="h-4 w-4" />
- 발주처 리비전 히스토리 ({response.attachment!.revisions.length}개)
- </h3>
- <div className="space-y-3">
- {response.attachment!.revisions
- .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
- .map((revision) => (
- <div
- key={revision.id}
- className={cn(
- "flex items-center justify-between p-4 rounded-lg border",
- revision.isLatest ? "bg-blue-50 border-blue-200" : "bg-white"
- )}
- >
- <div className="flex items-center gap-3 flex-1">
- <Badge variant={revision.isLatest ? "default" : "outline"}>
- {revision.revisionNo}
- </Badge>
- <div className="flex-1">
- <div className="font-medium text-sm">{revision.originalFileName}</div>
- <div className="text-xs text-muted-foreground">
- {formatFileSize(revision.fileSize)} • {formatDateTime(new Date(revision.createdAt))}
- </div>
- {revision.revisionComment && (
- <div className="text-xs text-muted-foreground mt-1 italic">
- "{revision.revisionComment}"
- </div>
- )}
- </div>
- </div>
-
- <div className="flex items-center gap-2">
- {revision.isLatest && (
- <Badge variant="secondary" className="text-xs">최신</Badge>
- )}
- {revision.revisionNo === response.respondedRevision && (
- <Badge variant="outline" className="text-xs text-green-600 border-green-300">
- 응답됨
- </Badge>
- )}
- <Button
- size="sm"
- variant="ghost"
- onClick={() => {
- if (revision.filePath) {
- handleFileDownload(
- revision.filePath,
- revision.originalFileName,
- "client",
- revision.id
- );
- }
- }}
- disabled={!revision.filePath}
- title="파일 다운로드"
- >
- <Download className="h-4 w-4" />
- </Button>
- </div>
- </div>
- ))}
- </div>
- </div>
- )}
-
- {/* 벤더 응답 파일들 */}
- {hasResponseFiles && (
- <div className="space-y-4">
- <h3 className="text-lg font-semibold flex items-center gap-2">
- <Upload className="h-4 w-4" />
- 벤더 응답 파일들 ({response.totalResponseFiles}개)
- </h3>
- <div className="space-y-3">
- {response.responseAttachments!
- .sort((a, b) => new Date(b.uploadedAt).getTime() - new Date(a.uploadedAt).getTime())
- .map((file) => (
- <div key={file.id} className="flex items-center justify-between p-4 rounded-lg border bg-green-50 border-green-200">
- <div className="flex items-center gap-3 flex-1">
- <Badge variant="outline" className="bg-green-100">
- 파일 #{file.fileSequence}
- </Badge>
- <div className="flex-1">
- <div className="font-medium text-sm">{file.originalFileName}</div>
- <div className="text-xs text-muted-foreground">
- {formatFileSize(file.fileSize)} • {formatDateTime(new Date(file.uploadedAt))}
- </div>
- {file.description && (
- <div className="text-xs text-muted-foreground mt-1 italic">
- "{file.description}"
- </div>
- )}
- </div>
- </div>
-
- <div className="flex items-center gap-2">
- {file.isLatestResponseFile && (
- <Badge variant="secondary" className="text-xs">최신</Badge>
- )}
- <Button
- size="sm"
- variant="ghost"
- onClick={() => {
- if (file.filePath) {
- handleFileDownload(
- file.filePath,
- file.originalFileName,
- "vendor",
- file.id
- );
- }
- }}
- disabled={!file.filePath}
- title="파일 다운로드"
- >
- <Download className="h-4 w-4" />
- </Button>
- </div>
- </div>
- ))}
- </div>
- </div>
- )}
-
- {!hasMultipleRevisions && !hasResponseFiles && (
- <div className="text-center text-muted-foreground py-8 bg-muted/20 rounded-lg">
- <FileText className="h-8 w-8 mx-auto mb-2 opacity-50" />
- <p>추가 파일이나 리비전 정보가 없습니다.</p>
- </div>
- )}
- </div>
- </SheetContent>
- </Sheet>
- );
-} \ No newline at end of file