"use client" import * as React from "react" import { format } from "date-fns" import { Package, ExternalLink } from "lucide-react" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { ScrollArea } from "@/components/ui/scroll-area" import { Skeleton } from "@/components/ui/skeleton" import { Separator } from "@/components/ui/separator" import { toast } from "sonner" import { RfqsLastView } from "@/db/schema" import { getRfqItemsAction } from "../service" // 품목 타입 interface RfqItem { id: number rfqsLastId: number | null rfqItem: string | null prItem: string | null prNo: string | null materialCode: string | null materialCategory: string | null acc: string | null materialDescription: string | null size: string | null deliveryDate: Date | null quantity: number | null uom: string | null grossWeight: number | null gwUom: string | null specNo: string | null specUrl: string | null trackingNo: string | null majorYn: boolean | null remark: string | null projectDef: string | null projectSc: string | null projectKl: string | null projectLc: string | null projectDl: string | null // RFQ 관련 정보 rfqCode: string | null rfqType: string | null rfqTitle: string | null itemCode: string | null itemName: string | null projectCode: string | null projectName: string | null } interface ItemStatistics { total: number major: number regular: number totalQuantity: number totalWeight: number } interface RfqItemsDialogProps { isOpen: boolean onClose: () => void rfqData: RfqsLastView } export function RfqItemsDialog({ isOpen, onClose, rfqData }: RfqItemsDialogProps) { const [items, setItems] = React.useState([]) const [statistics, setStatistics] = React.useState(null) const [isLoading, setIsLoading] = React.useState(false) // 품목 목록 로드 React.useEffect(() => { if (!isOpen || !rfqData.id) return const loadItems = async () => { setIsLoading(true) try { const result = await getRfqItemsAction(rfqData.id) console.log('RfqItemsDialog rfqId:', rfqData.id); console.log('RfqItemsDialog items result:', result); if (result.success) { setItems(result.data) setStatistics(result.statistics) } else { toast.error(result.error || "품목을 불러오는데 실패했습니다") setItems([]) setStatistics(null) } } catch (error) { console.error("품목 로드 오류:", error) toast.error("품목을 불러오는데 실패했습니다") setItems([]) setStatistics(null) } finally { setIsLoading(false) } } loadItems() }, [isOpen, rfqData.id]) // 사양서 링크 열기 const handleOpenSpec = (specUrl: string) => { window.open(specUrl, '_blank', 'noopener,noreferrer') } // 수량 포맷팅 const formatQuantity = (quantity: number | null, uom: string | null) => { if (!quantity) return "-" return `${quantity.toLocaleString()}${uom ? ` ${uom}` : ""}` } // 중량 포맷팅 const formatWeight = (weight: number | null, uom: string | null) => { if (!weight) return "-" return `${weight.toLocaleString()} ${uom || "KG"}` } return ( 견적 품목 목록 {rfqData.rfqCode} - {rfqData.rfqTitle || rfqData.itemName || "품목 정보"} {/* 통계 정보 */} {statistics && !isLoading && ( <>
{statistics.total}
전체 품목
{statistics.major}
주요 품목
{statistics.regular}
일반 품목
{statistics.totalQuantity.toLocaleString()}
총 수량
{statistics.totalWeight.toLocaleString()}
총 중량 (KG)
)} {isLoading ? ( 구분 자재코드 자재명 수량 중량 납기일 PR번호 사양 비고 {[...Array(3)].map((_, i) => ( ))}
) : items.length === 0 ? (

품목이 없습니다.

) : ( 구분 자재코드 자재명 수량 중량 납기일 PR번호 사양 프로젝트 비고 {items.map((item, index) => (
#{index + 1} {item.majorYn && ( 주요 )}
{item.materialCode || "-"} {item.acc && ( ACC: {item.acc} )}
{item.materialDescription || "-"} {item.materialCategory && ( {item.materialCategory} )} {item.size && ( 크기: {item.size} )}
{formatQuantity(item.quantity, item.uom)} {formatWeight(item.grossWeight, item.gwUom)} {item.deliveryDate ? format(new Date(item.deliveryDate), "yyyy-MM-dd") : "-"}
{item.prNo || "-"} {item.prItem && item.prItem !== item.prNo && ( {item.prItem} )}
{item.specNo && ( {item.specNo} )} {item.specUrl && ( )} {item.trackingNo && (
TRK: {item.trackingNo}
)}
{[ item.projectDef && `DEF: ${item.projectDef}`, item.projectSc && `SC: ${item.projectSc}`, item.projectKl && `KL: ${item.projectKl}`, item.projectLc && `LC: ${item.projectLc}`, item.projectDl && `DL: ${item.projectDl}` ].filter(Boolean).join(" | ") || "-"}
{item.remark ? (item.remark.length > 30 ? `${item.remark.slice(0, 30)}...` : item.remark) : "-"}
))}
)}
{/* 하단 통계 정보 */} {statistics && !isLoading && (
총 {statistics.total}개 품목 (주요: {statistics.major}개, 일반: {statistics.regular}개) 전체 수량: {statistics.totalQuantity.toLocaleString()} | 전체 중량: {statistics.totalWeight.toLocaleString()} KG
)}
) }