"use client" import * as React from "react" import { Eye, Building2, User, Calendar, CheckCircle2, Clock, MessageSquare, Award, FileText, Paperclip, Download, File, BarChart3 } from "lucide-react" import { Dialog, DialogContent, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Separator } from "@/components/ui/separator" import { Skeleton } from "@/components/ui/skeleton" import { PeriodicEvaluationView } from "@/db/schema" import { getEvaluationDetails} from "../service" import { AttachmentDetail, EvaluationDetailResponse } from "@/types/evaluation-form" // 파일 다운로드 유틸리티 import import { downloadFile, formatFileSize, getFileInfo } from "@/lib/file-download" interface EvaluationDetailsDialogProps { open: boolean onOpenChange: (open: boolean) => void evaluation: PeriodicEvaluationView | null } // 카테고리별 색상 매핑 const getCategoryBadgeVariant = (category: string) => { switch (category) { case "quality": return "default" case "delivery": return "secondary" case "price": return "outline" case "cooperation": return "destructive" default: return "outline" } } // 카테고리명 매핑 const CATEGORY_LABELS = { "customer-service": "CS", administrator: "관리자", procurement: "구매", design: "설계", sourcing: "조달", quality: "품질" } as const const CATEGORY_LABELS2 = { bonus: "가점항목", delivery: "납기", management: "경영현황", penalty: "감점항목", procurement: "구매", quality: "품질" } as const export function EvaluationDetailsDialog({ open, onOpenChange, evaluation, }: EvaluationDetailsDialogProps) { const [isLoading, setIsLoading] = React.useState(false) const [evaluationDetails, setEvaluationDetails] = React.useState(null) // 첨부파일 다운로드 핸들러 - downloadFile 사용 const handleDownloadAttachment = async (attachment: AttachmentDetail) => { try { await downloadFile( attachment.publicPath, attachment.originalFileName, { action: 'download', showToast: true, showSuccessToast: true, onError: (error) => { console.error("파일 다운로드 실패:", error) }, onSuccess: (fileName, fileSize) => { console.log("파일 다운로드 성공:", fileName, fileSize ? formatFileSize(fileSize) : '') } } ) } catch (error) { console.error("다운로드 처리 중 오류:", error) } } // 평가 상세 정보 로드 React.useEffect(() => { if (open && evaluation?.id) { const loadEvaluationDetails = async () => { try { setIsLoading(true) const details = await getEvaluationDetails(evaluation.id) setEvaluationDetails(details) } catch (error) { console.error("Failed to load evaluation details:", error) } finally { setIsLoading(false) } } loadEvaluationDetails() } }, [open, evaluation?.id]) // 다이얼로그 닫을 때 데이터 리셋 React.useEffect(() => { if (!open) { setEvaluationDetails(null) } }, [open]) if (!evaluation) return null return ( {/* 고정 헤더 */} 평가 상세 {/* 평가 기본 정보 */} 평가 정보
{/* 협력업체 */}
협력업체: {evaluation.vendorName} ({evaluation.vendorCode})
{/* 평가년도 */}
년도: {evaluation.evaluationYear}년
{/* 구분 */}
구분: {evaluation.division === "PLANT" ? "해양" : "조선"}
{/* 진행상태 */}
상태: {evaluation.status}
{/* 평가점수/등급 */}
평가점수/등급: {evaluation.evaluationScore ? (
{Number(evaluation.evaluationScore).toFixed(1)}점 {evaluation.evaluationGrade && ( {evaluation.evaluationGrade} )}
) : ( - )}
{/* 확정점수/등급 */}
확정점수/등급: {evaluation.finalScore ? (
{Number(evaluation.finalScore).toFixed(1)}점 {evaluation.finalGrade && ( {evaluation.finalGrade} )}
) : ( 미확정 )}
{/* 스크롤 가능한 컨텐츠 영역 */}
{isLoading ? (
) : evaluationDetails ? (
{/* 통합 평가 테이블 */} 평가 상세 내역 {evaluationDetails.reviewerDetails.some(r => r.evaluationItems.length > 0) ? ( 담당자 평가부문 항목 구분 범위 선택옵션 점수 첨부파일 의견 {evaluationDetails.reviewerDetails.map((reviewer) => reviewer.evaluationItems.map((item, index) => (
{reviewer.departmentName}
{reviewer.reviewerName}
{CATEGORY_LABELS[item.category as keyof typeof CATEGORY_LABELS] || item.category} {CATEGORY_LABELS2[item.item as keyof typeof CATEGORY_LABELS2] || item.item} {item.classification} {item.range || "-"} {item.scoreType === "variable" ? ( 직접 입력 ) : ( item.selectedDetail || "-" )} {item.score !== null ? ( {item.score.toFixed(1)} ) : ( - )} {/* 📎 첨부파일 컬럼 - 개선된 버전 */} {item.attachments.length > 0 ? (
{item.attachments.map((attachment) => { const fileInfo = getFileInfo(attachment.originalFileName) return (
{fileInfo.icon} {attachment.originalFileName}
{attachment.originalFileName}
크기: {formatFileSize(attachment.fileSize)}
타입: {fileInfo.type}
{attachment.description && (
설명: {attachment.description}
)}
업로드: {attachment.uploadedByName}
{fileInfo.canPreview ? "미리보기 가능" : "다운로드만 가능"}
) })} {item.attachments.length > 1 && (
총 {formatFileSize(item.attachmentTotalSize)}
)}
) : (
첨부파일 없음
)}
{item.comment || ( 의견 없음 )}
)) )}
) : (
평가 항목이 없습니다
)}
{/* 리뷰어별 종합 의견 (있는 경우만) */} {evaluationDetails.reviewerDetails.some(r => r.reviewerComment) && ( 종합 의견 {evaluationDetails.reviewerDetails .filter(reviewer => reviewer.reviewerComment) .map((reviewer) => (
{reviewer.departmentName} {reviewer.reviewerName} {reviewer.totalAttachments > 0 && ( {reviewer.totalAttachments}개 파일 )}
{reviewer.reviewerComment}
))}
)} {/* 📎 첨부파일 요약 (파일이 많은 경우) */} {evaluationDetails.attachmentStats.totalFiles > 5 && ( 첨부파일 요약
전체 파일 수
{evaluationDetails.attachmentStats.totalFiles}개
전체 파일 크기
{formatFileSize(evaluationDetails.attachmentStats.totalSize)}
첨부 질문 수
{evaluationDetails.attachmentStats.questionsWithAttachments}개
첨부 담당자 수
{evaluationDetails.attachmentStats.reviewersWithAttachments}명
)} {evaluationDetails.reviewerDetails.length === 0 && (
배정된 리뷰어가 없습니다
)}
) : (
평가 상세 정보를 불러올 수 없습니다
)}
{/* 고정 푸터 */}
) }