summaryrefslogtreecommitdiff
path: root/lib/rfq-last/vendor-response/rfq-items-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rfq-last/vendor-response/rfq-items-dialog.tsx')
-rw-r--r--lib/rfq-last/vendor-response/rfq-items-dialog.tsx360
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