From 90f79a7a691943a496f67f01c1e493256070e4de Mon Sep 17 00:00:00 2001 From: dujinkim Date: Mon, 7 Jul 2025 01:44:45 +0000 Subject: (대표님) 변경사항 20250707 10시 43분 - unstaged 변경사항 추가 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/evaluation/table/evaluation-details-dialog.tsx | 366 +++++++++++++++++++++ 1 file changed, 366 insertions(+) create mode 100644 lib/evaluation/table/evaluation-details-dialog.tsx (limited to 'lib/evaluation/table/evaluation-details-dialog.tsx') diff --git a/lib/evaluation/table/evaluation-details-dialog.tsx b/lib/evaluation/table/evaluation-details-dialog.tsx new file mode 100644 index 00000000..df4ef016 --- /dev/null +++ b/lib/evaluation/table/evaluation-details-dialog.tsx @@ -0,0 +1,366 @@ +"use client" + +import * as React from "react" +import { + Eye, + Building2, + User, + Calendar, + CheckCircle2, + Clock, + MessageSquare, + Award, + FileText +} from "lucide-react" + +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog" +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, type EvaluationDetailData } from "../service" + +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<{ + evaluationInfo: any + reviewerDetails: EvaluationDetailData[] + } | null>(null) + + // 평가 상세 정보 로드 + 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} +
+
+
+ {/* + {reviewer.isCompleted ? ( + + + 완료 + + ) : ( + + + 진행중 + + )} + */} + + + {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.comment || ( + 의견 없음 + )} + +
+ )) + )} +
+
+ ) : ( +
+ +
평가 항목이 없습니다
+
+ )} +
+
+ + {/* 리뷰어별 종합 의견 (있는 경우만) */} + {evaluationDetails.reviewerDetails.some(r => r.reviewerComment) && ( + + + + + 종합 의견 + + + + {evaluationDetails.reviewerDetails + .filter(reviewer => reviewer.reviewerComment) + .map((reviewer) => ( +
+
+ {reviewer.departmentName} + {reviewer.reviewerName} +
+
+ {reviewer.reviewerComment} +
+
+ ))} +
+
+ )} + + {evaluationDetails.reviewerDetails.length === 0 && ( + + +
+ +
배정된 리뷰어가 없습니다
+
+
+
+ )} +
+ ) : ( + + +
+ 평가 상세 정보를 불러올 수 없습니다 +
+
+
+ )} + +
+ +
+
+
+ ) +} \ No newline at end of file -- cgit v1.2.3