"use client" import * as React from "react" import { format } from "date-fns" import { ko } from "date-fns/locale" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { FileText, Users, CheckCircle, Clock, AlertCircle, Download, File, MessageSquare } from "lucide-react" import { getComplianceResponse, getComplianceResponseAnswers, getComplianceResponseFilesByResponseId, getComplianceSurveyTemplate, getComplianceQuestions, } from "./services" import { AgreementCommentList } from "@/lib/basic-contract/agreement-comments/agreement-comment-list" interface ComplianceResponseDetailProps { templateId: number responseId: number promises?: Promise } export function ComplianceResponseDetail({ templateId, responseId, promises }: ComplianceResponseDetailProps) { const [response, setResponse] = React.useState(null) const [answers, setAnswers] = React.useState([]) const [files, setFiles] = React.useState([]) const [template, setTemplate] = React.useState(null) const [questions, setQuestions] = React.useState([]) const [loading, setLoading] = React.useState(true) React.useEffect(() => { const fetchResponseData = async () => { try { let responseData, answersData, filesData, templateData, questionsData; if (promises) { [responseData, answersData, filesData, templateData, questionsData] = await promises; } else { [responseData, answersData, filesData, templateData, questionsData] = await Promise.all([ getComplianceResponse(responseId), getComplianceResponseAnswers(responseId), getComplianceResponseFilesByResponseId(responseId), getComplianceSurveyTemplate(templateId), getComplianceQuestions(templateId) ]); } setResponse(responseData) setAnswers(answersData) setFiles(filesData) setTemplate(templateData) setQuestions(questionsData) } catch (error) { console.error("Error fetching response data:", error) } finally { setLoading(false) } } fetchResponseData() }, [templateId, responseId, promises]) const getStatusIcon = (status: string) => { switch (status) { case 'COMPLETED': return case 'IN_PROGRESS': return case 'REVIEWED': return default: return } } const getStatusText = (status: string) => { switch (status) { case 'COMPLETED': return '완료' case 'IN_PROGRESS': return '진행중' case 'REVIEWED': return '검토완료' default: return '알 수 없음' } } const getQuestionText = (questionId: number) => { const question = questions.find(q => q.id === questionId) return question ? question.questionText : '질문을 찾을 수 없습니다' } const getQuestionNumber = (questionId: number) => { const question = questions.find(q => q.id === questionId) return question ? question.questionNumber : '-' } const hasFileUpload = (questionId: number) => { const question = questions.find(q => q.id === questionId) return question ? question.hasFileUpload : false } const isQuestionRedFlag = (questionId: number) => { const question = questions.find(q => q.id === questionId) return question ? question.isRedFlag : false } const isRedFlagTriggered = (answer: any) => { const isRedFlag = isQuestionRedFlag(answer.questionId) const answerValue = (answer.answerValue ?? '').toString().trim().toUpperCase() return isRedFlag && answerValue === 'YES' } // 파일 다운로드 핸들러 const handleFileDownload = async (file: any) => { try { // 파일 다운로드 API 호출 const response = await fetch(`/api/compliance/files/download?fileId=${file.id}`); if (!response.ok) { throw new Error('파일 다운로드에 실패했습니다'); } // Blob으로 파일 데이터 받기 const blob = await response.blob(); // 임시 URL 생성하여 다운로드 const url = window.URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = file.fileName; document.body.appendChild(link); link.click(); // 정리 document.body.removeChild(link); window.URL.revokeObjectURL(url); console.log("✅ 파일 다운로드 성공:", file.fileName); } catch (error) { console.error("❌ 파일 다운로드 실패:", error); alert(`파일 다운로드에 실패했습니다: ${error instanceof Error ? error.message : '알 수 없는 오류'}`); } } if (loading) { return (
) } if (!response) { return (
응답을 찾을 수 없습니다.
) } return (
{/* 응답 정보 */} 설문조사 응답 정보

{template?.name || '-'}

{response.vendorName ? ( {response.vendorName} ) : ( 기본계약 ID: {response.basicContractId} )}

{response.vendorCode && (

Vendor Code: {response.vendorCode}

)}
{getStatusIcon(response.status)} {getStatusText(response.status)}

{response.completedAt ? format(new Date(response.completedAt), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-' }

{response.createdAt ? format(new Date(response.createdAt), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-' }

{response.updatedAt ? format(new Date(response.updatedAt), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-' }

{/* 답변 목록 */} 답변 목록 ({answers.length}개) {answers.length === 0 ? (
아직 답변이 없습니다.
) : (
{answers.map((answer) => { const redFlagTriggered = isRedFlagTriggered(answer) return (
{getQuestionNumber(answer.questionId)} {getQuestionText(answer.questionId)} {/* {isQuestionRedFlag(answer.questionId) && ( RED FLAG )} */}
{/* 답변 값 */} {answer.answerValue && (

{answer.answerValue}

{/* {redFlagTriggered && ( Red Flag 발생 )} */}
)} {/* 상세 설명 */} {answer.detailText && (

{answer.detailText}

)} {/* 기타 텍스트 */} {answer.otherText && (

{answer.otherText}

)} {/* 퍼센트 값 */} {answer.percentageValue && (

{answer.percentageValue}%

)} {hasFileUpload(answer.questionId) && (
{files.filter(file => file.answerId === answer.id).length > 0 ? (
{files .filter(file => file.answerId === answer.id) .map((file) => (
{file.fileName} ({file.fileSize ? `${(file.fileSize / 1024).toFixed(1)} KB` : '크기 정보 없음'})
))}
) : (

첨부된 파일이 없습니다

)}
)} {/* 답변 생성일 */}
답변일: {answer.createdAt ? format(new Date(answer.createdAt), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-' }
) })}
)}
{/* 검토 정보 */} {response.reviewedBy && ( 검토 정보

{response.reviewerName ? ( {response.reviewerName} ) : ( 사용자 ID: {response.reviewedBy} )}

{response.reviewerEmail && (

{response.reviewerEmail}

)}

{response.reviewedAt ? format(new Date(response.reviewedAt), 'yyyy-MM-dd HH:mm', { locale: ko }) : '-' }

{response.reviewNotes && (

{response.reviewNotes}

)}
)} {/* 협의 코멘트 - Red Flag 발생 시 당사가 먼저 코멘트를 달 수 있도록 */} {response.basicContractId && ( 협의 코멘트
)}
) }