"use client" import * as React from "react" import { useEffect, useState } from "react" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Skeleton } from "@/components/ui/skeleton" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { toast } from "sonner" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog" // Lucide 아이콘 import { Plus, Minus, CheckCircle, Loader2 } from "lucide-react" import { getTechSalesVendorQuotationsWithJoin } from "@/lib/techsales-rfq/service" import { acceptTechSalesVendorQuotationAction } from "@/lib/techsales-rfq/actions" import { formatCurrency, formatDate } from "@/lib/utils" import { techSalesVendorQuotations } from "@/db/schema/techSales" // 기술영업 견적 정보 타입 interface TechSalesVendorQuotation { id: number rfqId: number vendorId: number vendorName?: string | null totalPrice: string | null currency: string | null validUntil: Date | null status: string remark: string | null submittedAt: Date | null acceptedAt: Date | null createdAt: Date updatedAt: Date } interface VendorQuotationComparisonDialogProps { open: boolean onOpenChange: (open: boolean) => void selectedRfq: { id: number; rfqCode: string | null; status: string; [key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any } | null } export function VendorQuotationComparisonDialog({ open, onOpenChange, selectedRfq, }: VendorQuotationComparisonDialogProps) { const [isLoading, setIsLoading] = useState(false) const [quotations, setQuotations] = useState([]) const [selectedVendorId, setSelectedVendorId] = useState(null) const [isAccepting, setIsAccepting] = useState(false) const [showConfirmDialog, setShowConfirmDialog] = useState(false) useEffect(() => { async function loadQuotationData() { if (!open || !selectedRfq?.id) return try { setIsLoading(true) // 기술영업 견적 목록 조회 (제출된 견적만) const result = await getTechSalesVendorQuotationsWithJoin({ rfqId: selectedRfq.id, page: 1, perPage: 100, filters: [ { id: "status" as keyof typeof techSalesVendorQuotations, value: "Submitted", type: "select" as const, operator: "eq" as const, rowId: "status" } ] }) setQuotations(result.data || []) } catch (error) { console.error("견적 데이터 로드 오류:", error) toast.error("견적 데이터를 불러오는 데 실패했습니다") } finally { setIsLoading(false) } } loadQuotationData() }, [open, selectedRfq]) // 견적 상태 -> 뱃지 색 const getStatusBadgeVariant = (status: string) => { switch (status) { case "Submitted": return "default" case "Accepted": return "default" case "Rejected": return "destructive" case "Revised": return "destructive" default: return "secondary" } } // 벤더 선택 핸들러 const handleSelectVendor = (vendorId: number) => { setSelectedVendorId(vendorId) setShowConfirmDialog(true) } // 벤더 선택 확정 const handleConfirmSelection = async () => { if (!selectedVendorId) return try { setIsAccepting(true) // 선택된 견적의 ID 찾기 const selectedQuotation = quotations.find(q => q.vendorId === selectedVendorId) if (!selectedQuotation) { toast.error("선택된 견적을 찾을 수 없습니다") return } // 벤더 선택 API 호출 const result = await acceptTechSalesVendorQuotationAction(selectedQuotation.id) if (result.success) { toast.success(result.message || "벤더가 선택되었습니다") setShowConfirmDialog(false) onOpenChange(false) // 페이지 새로고침 또는 데이터 재로드 window.location.reload() } else { toast.error(result.error || "벤더 선택에 실패했습니다") } } catch (error) { console.error("벤더 선택 오류:", error) toast.error("벤더 선택에 실패했습니다") } finally { setIsAccepting(false) } } const selectedVendor = quotations.find(q => q.vendorId === selectedVendorId) return ( <> 벤더 견적 비교 및 선택 {selectedRfq ? `RFQ ${selectedRfq.rfqCode} - 제출된 견적을 비교하고 벤더를 선택하세요` : ""} {isLoading ? (
) : quotations.length === 0 ? (
제출된(Submitted) 견적이 없습니다
) : (
항목 {quotations.map((q) => (
{q.vendorName || `벤더 ID: ${q.vendorId}`}
))}
{/* 견적 상태 */} 견적 상태 {quotations.map((q) => ( {q.status} ))} {/* 총 금액 */} 총 금액 {quotations.map((q) => ( {q.totalPrice ? formatCurrency(Number(q.totalPrice), q.currency || 'USD') : '-'} ))} {/* 통화 */} 통화 {quotations.map((q) => ( {q.currency || '-'} ))} {/* 유효기간 */} 유효 기간 {quotations.map((q) => ( {q.validUntil ? formatDate(q.validUntil, "KR") : '-'} ))} {/* 제출일 */} 제출일 {quotations.map((q) => ( {q.submittedAt ? formatDate(q.submittedAt, "KR") : '-'} ))} {/* 비고 */} 비고 {quotations.map((q) => ( {q.remark || "-"} ))}
)}
{/* 벤더 선택 확인 다이얼로그 */} 벤더 선택 확인 {selectedVendor?.vendorName || `벤더 ID: ${selectedVendorId}`}를 선택하시겠습니까?

선택된 벤더의 견적이 승인되며, 다른 벤더들의 견적은 자동으로 거절됩니다. 이 작업은 되돌릴 수 없습니다.
취소 {isAccepting && } 확인
) }