"use client" import * as React from "react" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { Badge } from "@/components/ui/badge" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { FileText, Users, Calendar, Send } from "lucide-react" import { toast } from "sonner" import { PeriodicEvaluationView } from "@/db/schema" import { checkExistingSubmissions, requestDocumentsFromVendors } from "../service" // ================================================================ // 2. 협력업체 자료 요청 다이얼로그 // ================================================================ interface RequestDocumentsDialogProps { open: boolean onOpenChange: (open: boolean) => void evaluations: PeriodicEvaluationView[] onSuccess: () => void } interface EvaluationWithSubmissionStatus extends PeriodicEvaluationView { hasExistingSubmission?: boolean submissionDate?: Date | null } export function RequestDocumentsDialog({ open, onOpenChange, evaluations, onSuccess, }: RequestDocumentsDialogProps) { console.log(evaluations) const [isLoading, setIsLoading] = React.useState(false) const [isCheckingStatus, setIsCheckingStatus] = React.useState(false) const [message, setMessage] = React.useState("") const [evaluationsWithStatus, setEvaluationsWithStatus] = React.useState([]) // 제출대기 상태인 평가들만 필터링 const pendingEvaluations = React.useMemo(() => evaluations.filter(e => e.status === "PENDING_SUBMISSION"), [evaluations] ) React.useEffect(() => { if (!open) return; // 대기 중 평가가 없으면 초기화 if (pendingEvaluations.length === 0) { setEvaluationsWithStatus([]); setIsCheckingStatus(false); return; } // 상태 확인 (async () => { setIsCheckingStatus(true); try { const ids = pendingEvaluations.map(e => e.id); const existing = await checkExistingSubmissions(ids); setEvaluationsWithStatus( pendingEvaluations.map(e => ({ ...e, hasExistingSubmission: existing.some(s => s.periodicEvaluationId === e.id), submissionDate: existing.find(s => s.periodicEvaluationId === e.id)?.createdAt ?? null, })), ); } catch (err) { console.error(err); setEvaluationsWithStatus( pendingEvaluations.map(e => ({ ...e, hasExistingSubmission: false })), ); } finally { setIsCheckingStatus(false); } })(); }, [open, pendingEvaluations]); // 함수 대신 값에만 의존 // 새 요청과 재요청 분리 const newRequests = evaluationsWithStatus.filter(e => !e.hasExistingSubmission) const reRequests = evaluationsWithStatus.filter(e => e.hasExistingSubmission) const handleSubmit = async () => { if (!message.trim()) { toast.error("요청 메시지를 입력해주세요.") return } setIsLoading(true) try { // 서버 액션 데이터 준비 const requestData = evaluationsWithStatus.map(evaluation => ({ periodicEvaluationId: evaluation.id, companyId: evaluation.vendorId, evaluationYear: evaluation.evaluationYear, evaluationRound: evaluation.evaluationPeriod, message: message.trim() })) // 서버 액션 호출 const result = await requestDocumentsFromVendors(requestData) if (result.success) { toast.success(result.message) onSuccess() onOpenChange(false) setMessage("") } else { toast.error(result.message) } } catch (error) { console.error('Error requesting documents:', error) toast.error("자료 요청 발송 중 오류가 발생했습니다.") } finally { setIsLoading(false) } } return ( 협력업체 자료 요청 선택된 평가의 협력업체들에게 평가 자료 제출을 요청합니다.
{isCheckingStatus ? (
요청 상태를 확인하고 있습니다...
) : ( <> {/* 신규 요청 대상 업체 */} {newRequests.length > 0 && ( 신규 요청 대상 ({newRequests.length}개 업체) {newRequests.map((evaluation) => (
{evaluation.vendorName}
{evaluation.vendorCode} 신규
))}
)} {/* 재요청 대상 업체 */} {reRequests.length > 0 && ( 재요청 대상 ({reRequests.length}개 업체) {reRequests.map((evaluation) => (
{evaluation.vendorName}
{evaluation.vendorCode} 재요청 {evaluation.submissionDate && ( {new Intl.DateTimeFormat("ko-KR", { month: "2-digit", day: "2-digit", }).format(new Date(evaluation.submissionDate))} )}
))}
)} {/* 요청 대상이 없는 경우 */} {!isCheckingStatus && evaluationsWithStatus.length === 0 && (
요청할 수 있는 평가가 없습니다.
)} )} {/* 요청 메시지 */}