diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-12 10:42:36 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-12 10:42:36 +0000 |
| commit | 8642ee064ddf96f1db2b948b4cc8bbbd6cfee820 (patch) | |
| tree | 36bd57d147ba929f1d72918d1fb91ad2c4778624 /lib/bidding/detail/table/quotation-history-dialog.tsx | |
| parent | 57ea2f740abf1c7933671561cfe0e421fb5ef3fc (diff) | |
(최겸) 구매 일반계약, 입찰 수정
Diffstat (limited to 'lib/bidding/detail/table/quotation-history-dialog.tsx')
| -rw-r--r-- | lib/bidding/detail/table/quotation-history-dialog.tsx | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/lib/bidding/detail/table/quotation-history-dialog.tsx b/lib/bidding/detail/table/quotation-history-dialog.tsx new file mode 100644 index 00000000..b816368a --- /dev/null +++ b/lib/bidding/detail/table/quotation-history-dialog.tsx @@ -0,0 +1,254 @@ +'use client' + +import * as React from '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 { formatDate } from '@/lib/utils' +import { History, Eye } from 'lucide-react' + +interface QuotationHistoryItem { + id: string + round: number + submittedAt: Date + totalAmount: number + currency: string + vsTargetPrice: number // 퍼센트 + items: Array<{ + itemCode: string + itemName: string + specification: string + quantity: number + unit: string + unitPrice: number + totalPrice: number + deliveryDate: Date + }> +} + +interface QuotationHistoryDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + vendorName: string + history: QuotationHistoryItem[] + biddingCurrency: string + targetPrice?: number +} + +export function QuotationHistoryDialog({ + open, + onOpenChange, + vendorName, + history, + biddingCurrency, + targetPrice +}: QuotationHistoryDialogProps) { + const [selectedHistory, setSelectedHistory] = React.useState<QuotationHistoryItem | null>(null) + const [detailDialogOpen, setDetailDialogOpen] = React.useState(false) + + const handleViewDetail = (historyItem: QuotationHistoryItem) => { + setSelectedHistory(historyItem) + setDetailDialogOpen(true) + } + + const handleDetailDialogClose = () => { + setDetailDialogOpen(false) + setSelectedHistory(null) + } + + return ( + <> + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto"> + <DialogHeader> + <DialogTitle className="flex items-center gap-2"> + <History className="h-5 w-5" /> + 견적 히스토리 - {vendorName} + </DialogTitle> + <DialogDescription> + {vendorName} 업체의 제출한 견적 내역을 확인할 수 있습니다. + </DialogDescription> + </DialogHeader> + + <div className="space-y-4"> + {history.length > 0 ? ( + <Table> + <TableHeader> + <TableRow> + <TableHead>차수</TableHead> + <TableHead>제출일시</TableHead> + <TableHead className="text-right">견적금액</TableHead> + <TableHead className="text-right">내정가대비 (%)</TableHead> + <TableHead className="text-center">액션</TableHead> + </TableRow> + </TableHeader> + <TableBody> + {history.map((item) => ( + <TableRow key={item.id}> + <TableCell className="font-medium"> + {item.round}차 + </TableCell> + <TableCell> + {formatDate(item.submittedAt, 'KR')} + </TableCell> + <TableCell className="text-right font-mono"> + {item.totalAmount.toLocaleString()} {item.currency} + </TableCell> + <TableCell className="text-right"> + {targetPrice && targetPrice > 0 ? ( + <Badge + variant={item.vsTargetPrice <= 0 ? 'default' : 'destructive'} + > + {item.vsTargetPrice > 0 ? '+' : ''}{item.vsTargetPrice.toFixed(1)}% + </Badge> + ) : ( + '-' + )} + </TableCell> + <TableCell className="text-center"> + <Button + variant="outline" + size="sm" + onClick={() => handleViewDetail(item)} + > + <Eye className="h-4 w-4 mr-1" /> + 상세 + </Button> + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> + ) : ( + <div className="text-center py-8 text-muted-foreground"> + 제출된 견적 내역이 없습니다. + </div> + )} + </div> + </DialogContent> + </Dialog> + + {/* 상세 다이얼로그 */} + {selectedHistory && ( + <QuotationHistoryDetailDialog + open={detailDialogOpen} + onOpenChange={handleDetailDialogClose} + vendorName={vendorName} + historyItem={selectedHistory} + /> + )} + </> + ) +} + +// 견적 히스토리 상세 다이얼로그 +interface QuotationHistoryDetailDialogProps { + open: boolean + onOpenChange: (open: boolean) => void + vendorName: string + historyItem: QuotationHistoryItem +} + +function QuotationHistoryDetailDialog({ + open, + onOpenChange, + vendorName, + historyItem +}: QuotationHistoryDetailDialogProps) { + return ( + <Dialog open={open} onOpenChange={onOpenChange}> + <DialogContent className="max-w-6xl max-h-[90vh] overflow-y-auto"> + <DialogHeader> + <DialogTitle> + 견적 상세 - {vendorName} ({historyItem.round}차) + </DialogTitle> + <DialogDescription> + 제출일시: {formatDate(historyItem.submittedAt, 'KR')} + </DialogDescription> + </DialogHeader> + + <div className="space-y-4"> + {/* 요약 정보 */} + <div className="grid grid-cols-3 gap-4 p-4 bg-muted/50 rounded-lg"> + <div> + <label className="text-sm font-medium text-muted-foreground">총 견적금액</label> + <div className="text-lg font-bold"> + {historyItem.totalAmount.toLocaleString()} {historyItem.currency} + </div> + </div> + <div> + <label className="text-sm font-medium text-muted-foreground">품목 수</label> + <div className="text-lg font-bold"> + {historyItem.items.length}개 + </div> + </div> + <div> + <label className="text-sm font-medium text-muted-foreground">제출일시</label> + <div className="text-sm"> + {formatDate(historyItem.submittedAt, 'KR')} + </div> + </div> + </div> + + {/* 품목 상세 테이블 */} + <Table> + <TableHeader> + <TableRow> + <TableHead>품목코드</TableHead> + <TableHead>품목명</TableHead> + <TableHead>규격</TableHead> + <TableHead className="text-right">수량</TableHead> + <TableHead>단위</TableHead> + <TableHead className="text-right">단가</TableHead> + <TableHead className="text-right">금액</TableHead> + <TableHead>납기요청일</TableHead> + </TableRow> + </TableHeader> + <TableBody> + {historyItem.items.map((item, index) => ( + <TableRow key={index}> + <TableCell className="font-mono text-sm"> + {item.itemCode} + </TableCell> + <TableCell className="font-medium"> + {item.itemName} + </TableCell> + <TableCell className="text-sm"> + {item.specification || '-'} + </TableCell> + <TableCell className="text-right"> + {item.quantity.toLocaleString()} + </TableCell> + <TableCell>{item.unit}</TableCell> + <TableCell className="text-right font-mono"> + {item.unitPrice.toLocaleString()} {historyItem.currency} + </TableCell> + <TableCell className="text-right font-mono"> + {item.totalPrice.toLocaleString()} {historyItem.currency} + </TableCell> + <TableCell className="text-sm"> + {formatDate(item.deliveryDate, 'KR')} + </TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </div> + </DialogContent> + </Dialog> + ) +} |
