import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Skeleton } from "@/components/ui/skeleton"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
import {
RefreshCw,
Download,
MessageSquare,
Clock,
CheckCircle2,
XCircle,
AlertCircle,
FileText,
Files,
AlertTriangle
} from "lucide-react"
import { formatDate, formatFileSize } from "@/lib/utils"
import { RequestRevisionDialog } from "./request-revision-dialog"
interface VendorResponsesPanelProps {
attachment: any
responses: any[]
isLoading: boolean
onRefresh: () => void
}
// 파일 다운로드 핸들러
async function handleFileDownload(filePath: string, fileName: string, fileId: number) {
try {
const params = new URLSearchParams({
path: filePath,
type: "vendor",
responseFileId: fileId.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}`);
}
const blob = await response.blob();
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 FilesList({ files }: { files: any[] }) {
if (files.length === 0) {
return (
업로드된 파일이 없습니다.
);
}
return (
{files.map((file, index) => (
{file.originalFileName}
{formatFileSize(file.fileSize)} • {formatDate(file.uploadedAt)}
{file.description && (
{file.description}
)}
))}
);
}
export function VendorResponsesPanel({
attachment,
responses,
isLoading,
onRefresh
}: VendorResponsesPanelProps) {
console.log(responses)
const getStatusIcon = (status: string) => {
switch (status) {
case 'RESPONDED':
return
case 'NOT_RESPONDED':
return
case 'WAIVED':
return
case 'REVISION_REQUESTED':
return
default:
return
}
}
const getStatusBadgeVariant = (status: string) => {
switch (status) {
case 'RESPONDED':
return 'default'
case 'NOT_RESPONDED':
return 'secondary'
case 'WAIVED':
return 'outline'
case 'REVISION_REQUESTED':
return 'destructive'
default:
return 'secondary'
}
}
if (isLoading) {
return (
{Array.from({ length: 3 }).map((_, i) => (
))}
)
}
return (
{/* 헤더 */}
벤더 응답 현황: {attachment.originalFileName}
{attachment.attachmentType}
시리얼: {attachment.serialNo}
등록: {formatDate(attachment.createdAt)}
{attachment.responseStats && (
응답률: {attachment.responseStats.responseRate}%
)}
{/* 테이블 */}
{responses.length === 0 ? (
이 문서에 대한 벤더 응답 정보가 없습니다.
) : (
벤더
국가
응답 상태
리비전
요청일
응답일
응답 파일
코멘트
액션
{responses.map((response) => (
{response.vendorName}
{response.vendorCode}
{response.vendorCountry}
{getStatusIcon(response.responseStatus)}
{response.responseStatus}
현재: {response.currentRevision}
{response.respondedRevision && (
응답: {response.respondedRevision}
)}
{formatDate(response.requestedAt)}
{response.respondedAt ? formatDate(response.respondedAt) : '-'}
{/* 응답 파일 컬럼 */}
{response.totalFiles > 0 ? (
{response.totalFiles}개
{response.totalFiles === 1 ? (
// 파일이 1개면 바로 다운로드
) : (
// 파일이 여러 개면 Popover로 목록 표시
응답 파일 목록 ({response.totalFiles}개)
)}
) : (
-
)}
{/* 벤더 응답 코멘트 */}
{response.responseComment && (
{response.responseComment}
)}
{/* 수정 요청 사유 */}
{response.revisionRequestComment && (
{response.revisionRequestComment}
)}
{!response.responseComment && !response.revisionRequestComment && (
-
)}
{/* 액션 컬럼 - 수정 요청 기능으로 변경 */}
{response.responseStatus === 'RESPONDED' && (
수정요청
}
/>
)}
{response.responseStatus === 'REVISION_REQUESTED' && (
수정 요청됨
)}
{(response.responseStatus === 'NOT_RESPONDED' || response.responseStatus === 'WAIVED') && (
-
)}
))}
)}
)
}