diff options
Diffstat (limited to 'lib/rfq-last/vendor-response/rfq-items-dialog.tsx')
| -rw-r--r-- | lib/rfq-last/vendor-response/rfq-items-dialog.tsx | 360 |
1 files changed, 0 insertions, 360 deletions
diff --git a/lib/rfq-last/vendor-response/rfq-items-dialog.tsx b/lib/rfq-last/vendor-response/rfq-items-dialog.tsx deleted file mode 100644 index 9790a1bd..00000000 --- a/lib/rfq-last/vendor-response/rfq-items-dialog.tsx +++ /dev/null @@ -1,360 +0,0 @@ -"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<RfqItem[]>([]) - const [statistics, setStatistics] = React.useState<ItemStatistics | null>(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) - - if (result.success) { - setItems(result.data) - setStatistics(result.statistics ?? null) - } 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') - } - - - return ( - <Dialog open={isOpen} onOpenChange={onClose}> - <DialogContent className="max-w-7xl h-[90vh] flex flex-col"> - <DialogHeader> - <DialogTitle>견적 품목 목록</DialogTitle> - <DialogDescription> - {rfqData.rfqCode} - {rfqData.rfqTitle || rfqData.itemName || "품목 정보"} - </DialogDescription> - </DialogHeader> - - {/* 통계 정보 */} - {statistics && !isLoading && ( - <> -<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-3 py-3"> -<div className="text-center"> - <div className="text-2xl font-bold text-primary">{statistics.total}</div> - <div className="text-xs text-muted-foreground">전체 품목</div> - </div> - <div className="text-center"> - <div className="text-2xl font-bold text-blue-600">{statistics.major}</div> - <div className="text-xs text-muted-foreground">주요 품목</div> - </div> - <div className="text-center"> - <div className="text-2xl font-bold text-gray-600">{statistics.regular}</div> - <div className="text-xs text-muted-foreground">일반 품목</div> - </div> - <div className="text-center"> - <div className="text-2xl font-bold text-green-600">{statistics.totalQuantity.toLocaleString()}</div> - <div className="text-xs text-muted-foreground">총 수량</div> - </div> - <div className="text-center"> - <div className="text-2xl font-bold text-orange-600">{statistics.totalWeight.toLocaleString()}</div> - <div className="text-xs text-muted-foreground">총 중량 (KG)</div> - </div> - </div> - <Separator /> - </> - )} - - <ScrollArea className="flex-1"> - {isLoading ? ( - <Table> - <TableHeader> - <TableRow> - <TableHead className="w-[60px]">구분</TableHead> - <TableHead className="w-[120px]">자재코드</TableHead> - <TableHead>자재명</TableHead> - <TableHead className="w-[80px]">수량</TableHead> - <TableHead className="w-[60px]">수량단위</TableHead> - <TableHead className="w-[80px]">중량</TableHead> - <TableHead className="w-[60px]">중량단위</TableHead> - <TableHead className="w-[100px]">납기일</TableHead> - <TableHead className="w-[100px]">PR번호</TableHead> - <TableHead className="w-[80px]">사양</TableHead> - <TableHead>비고</TableHead> - </TableRow> - </TableHeader> - <TableBody> - {[...Array(3)].map((_, i) => ( - <TableRow key={i}> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - <TableCell><Skeleton className="h-8 w-full" /></TableCell> - </TableRow> - ))} - </TableBody> - </Table> - ) : items.length === 0 ? ( - <div className="text-center text-muted-foreground py-12"> - <Package className="h-12 w-12 mx-auto mb-4 text-muted-foreground" /> - <p>품목이 없습니다.</p> - </div> - ) : ( - <Table> - <TableHeader> - <TableRow> - <TableHead className="w-[60px]">구분</TableHead> - <TableHead className="w-[120px]">자재코드</TableHead> - <TableHead>자재명</TableHead> - <TableHead className="w-[80px]">수량</TableHead> - <TableHead className="w-[60px]">수량단위</TableHead> - <TableHead className="w-[80px]">중량</TableHead> - <TableHead className="w-[60px]">중량단위</TableHead> - <TableHead className="w-[100px]">납기일</TableHead> - <TableHead className="w-[100px]">PR번호</TableHead> - <TableHead className="w-[100px]">사양</TableHead> - <TableHead className="w-[100px]">프로젝트</TableHead> - <TableHead>비고</TableHead> - </TableRow> - </TableHeader> - <TableBody> - {items.map((item, index) => ( - <TableRow key={item.id} className={item.majorYn ? "bg-blue-50 border-l-4 border-l-blue-500" : ""}> - <TableCell> - <div className="flex flex-col items-center gap-1"> - <span className="text-xs font-mono">#{index + 1}</span> - {item.majorYn && ( - <Badge variant="default" className="text-xs px-1 py-0"> - 주요 - </Badge> - )} - </div> - </TableCell> - <TableCell> - <div className="flex flex-col"> - <span className="font-mono text-sm font-medium">{item.materialCode || "-"}</span> - {item.acc && ( - <span className="text-xs text-muted-foreground font-mono"> - ACC: {item.acc} - </span> - )} - </div> - </TableCell> - <TableCell> - <div className="flex flex-col"> - <span className="text-sm font-medium" title={item.materialDescription || ""}> - {item.materialDescription || "-"} - </span> - {item.materialCategory && ( - <span className="text-xs text-muted-foreground"> - {item.materialCategory} - </span> - )} - {item.size && ( - <span className="text-xs text-muted-foreground"> - 크기: {item.size} - </span> - )} - </div> - </TableCell> - <TableCell> - <span className="text-sm font-medium"> - {item.quantity ? item.quantity.toLocaleString() : "-"} - </span> - </TableCell> - <TableCell> - <span className="text-sm text-muted-foreground"> - {item.uom || "-"} - </span> - </TableCell> - <TableCell> - <span className="text-sm font-medium"> - {item.grossWeight ? item.grossWeight.toLocaleString() : "-"} - </span> - </TableCell> - <TableCell> - <span className="text-sm text-muted-foreground"> - {item.gwUom || "-"} - </span> - </TableCell> - <TableCell> - <span className="text-sm"> - {item.deliveryDate ? format(new Date(item.deliveryDate), "yyyy-MM-dd") : "-"} - </span> - </TableCell> - <TableCell> - <div className="flex flex-col"> - <span className="text-xs font-mono">{item.prNo || "-"}</span> - {item.prItem && item.prItem !== item.prNo && ( - <span className="text-xs text-muted-foreground font-mono"> - {item.prItem} - </span> - )} - </div> - </TableCell> - <TableCell> - <div className="flex items-center gap-1"> - {item.specNo && ( - <span className="text-xs font-mono">{item.specNo}</span> - )} - {item.specUrl && ( - <Button - variant="ghost" - size="sm" - className="h-5 w-5 p-0" - onClick={() => handleOpenSpec(item.specUrl!)} - title="사양서 열기" - > - <ExternalLink className="h-3 w-3" /> - </Button> - )} - {item.trackingNo && ( - <div className="text-xs text-muted-foreground"> - TRK: {item.trackingNo} - </div> - )} - </div> - </TableCell> - <TableCell> - <div className="text-xs"> - {[ - item.projectDef && `${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(" | ") || "-"} - </div> - </TableCell> - <TableCell> - <span className="text-xs" title={item.remark || ""}> - {item.remark ? (item.remark.length > 30 ? `${item.remark.slice(0, 30)}...` : item.remark) : "-"} - </span> - </TableCell> - </TableRow> - ))} - </TableBody> - </Table> - )} - </ScrollArea> - - {/* 하단 통계 정보 */} - {statistics && !isLoading && ( - <div className="border-t pt-3 text-xs text-muted-foreground"> - <div className="flex justify-between items-center"> - <span> - 총 {statistics.total}개 품목 - (주요: {statistics.major}개, 일반: {statistics.regular}개) - </span> - <span> - 전체 수량: {statistics.totalQuantity.toLocaleString()} | - 전체 중량: {statistics.totalWeight.toLocaleString()} KG - </span> - </div> - </div> - )} - </DialogContent> - </Dialog> - ) -}
\ No newline at end of file |
