"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 { Separator } from "@/components/ui/separator" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion" import { FileText, Users, CheckCircle, Clock, AlertCircle, Download, File } from "lucide-react" import { getComplianceResponse, getComplianceResponseAnswers, getComplianceResponseFilesByResponseId, getComplianceSurveyTemplate, getComplianceQuestions, getComplianceQuestionOptions } from "./services" interface ComplianceResponseDetailProps { templateId: number responseId: number } export function ComplianceResponseDetail({ templateId, responseId }: 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 { const [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]) 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 getQuestionType = (questionId: number) => { const question = questions.find(q => q.id === questionId) return question ? question.questionType : '-' } // 파일 다운로드 핸들러 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, index) => (
{getQuestionNumber(answer.questionId)} {getQuestionText(answer.questionId)} {getQuestionType(answer.questionId)}
{/* 답변 값 */} {answer.answerValue && (

{answer.answerValue}

)} {/* 상세 설명 */} {answer.detailText && (

{answer.detailText}

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

{answer.otherText}

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

{answer.percentageValue}%

)} {/* 첨부파일 */}
{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}

)}
)}
) }