summaryrefslogtreecommitdiff
path: root/lib/itb/table/items-dialog.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-18 00:23:40 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-18 00:23:40 +0000
commitcf8dac0c6490469dab88a560004b0c07dbd48612 (patch)
treeb9e76061e80d868331e6b4277deecb9086f845f3 /lib/itb/table/items-dialog.tsx
parente5745fc0268bbb5770bc14a55fd58a0ec30b466e (diff)
(대표님) rfq, 계약, 서명 등
Diffstat (limited to 'lib/itb/table/items-dialog.tsx')
-rw-r--r--lib/itb/table/items-dialog.tsx167
1 files changed, 167 insertions, 0 deletions
diff --git a/lib/itb/table/items-dialog.tsx b/lib/itb/table/items-dialog.tsx
new file mode 100644
index 00000000..dd688ce9
--- /dev/null
+++ b/lib/itb/table/items-dialog.tsx
@@ -0,0 +1,167 @@
+// components/purchase-requests/items-dialog.tsx
+"use client";
+
+import * as React from "react";
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+ TableFooter,
+} from "@/components/ui/table";
+import { Badge } from "@/components/ui/badge";
+import { Package } from "lucide-react";
+
+interface Item {
+ id: string;
+ itemCode: string;
+ itemName: string;
+ specification: string;
+ quantity: number;
+ unit: string;
+ estimatedUnitPrice?: number;
+ remarks?: string;
+}
+
+interface ItemsDialogProps {
+ requestId: number;
+ requestCode: string;
+ items: Item[] | any;
+ open: boolean;
+ onOpenChange: (open: boolean) => void;
+}
+
+export function ItemsDialog({
+ requestId,
+ requestCode,
+ items,
+ open,
+ onOpenChange,
+}: ItemsDialogProps) {
+ // items가 없거나 배열이 아닌 경우 처리
+ const itemList = React.useMemo(() => {
+ if (!items || !Array.isArray(items)) return [];
+ return items;
+ }, [items]);
+
+ // 총액 계산
+ const totalAmount = React.useMemo(() => {
+ return itemList.reduce((sum, item) => {
+ const subtotal = (item.quantity || 0) * (item.estimatedUnitPrice || 0);
+ return sum + subtotal;
+ }, 0);
+ }, [itemList]);
+
+ // 총 수량 계산
+ const totalQuantity = React.useMemo(() => {
+ return itemList.reduce((sum, item) => sum + (item.quantity || 0), 0);
+ }, [itemList]);
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="max-w-5xl max-h-[80vh] overflow-hidden flex flex-col">
+ <DialogHeader>
+ <DialogTitle className="flex items-center gap-2">
+ <Package className="h-5 w-5" />
+ 품목 상세 정보
+ </DialogTitle>
+ <DialogDescription>
+ 요청번호: {requestCode} | 총 {itemList.length}개 품목
+ </DialogDescription>
+ </DialogHeader>
+
+ <div className="flex-1 overflow-auto">
+ {itemList.length === 0 ? (
+ <div className="flex items-center justify-center h-32">
+ <p className="text-muted-foreground">등록된 품목이 없습니다.</p>
+ </div>
+ ) : (
+ <Table>
+ <TableHeader className="sticky top-0 bg-background">
+ <TableRow>
+ <TableHead className="w-[50px]">번호</TableHead>
+ <TableHead className="w-[120px]">아이템 코드</TableHead>
+ <TableHead>아이템명</TableHead>
+ <TableHead>사양</TableHead>
+ <TableHead className="text-right w-[80px]">수량</TableHead>
+ <TableHead className="w-[60px]">단위</TableHead>
+ <TableHead className="text-right w-[120px]">예상 단가</TableHead>
+ <TableHead className="text-right w-[140px]">예상 금액</TableHead>
+ <TableHead className="w-[150px]">비고</TableHead>
+ </TableRow>
+ </TableHeader>
+ <TableBody>
+ {itemList.map((item, index) => {
+ const subtotal = (item.quantity || 0) * (item.estimatedUnitPrice || 0);
+ return (
+ <TableRow key={item.id || index}>
+ <TableCell className="text-center text-muted-foreground">
+ {index + 1}
+ </TableCell>
+ <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 font-medium">
+ {item.quantity?.toLocaleString('ko-KR')}
+ </TableCell>
+ <TableCell className="text-center">
+ {item.unit}
+ </TableCell>
+ <TableCell className="text-right">
+ {item.estimatedUnitPrice
+ ? new Intl.NumberFormat('ko-KR').format(item.estimatedUnitPrice)
+ : "-"}
+ </TableCell>
+ <TableCell className="text-right font-medium">
+ {subtotal > 0
+ ? new Intl.NumberFormat('ko-KR').format(subtotal)
+ : "-"}
+ </TableCell>
+ <TableCell className="text-sm text-muted-foreground">
+ {item.remarks || "-"}
+ </TableCell>
+ </TableRow>
+ );
+ })}
+ </TableBody>
+ <TableFooter>
+ <TableRow className="bg-muted/50">
+ <TableCell colSpan={4} className="font-medium">
+ 합계
+ </TableCell>
+ <TableCell className="text-right font-bold">
+ {totalQuantity.toLocaleString('ko-KR')}
+ </TableCell>
+ <TableCell></TableCell>
+ <TableCell></TableCell>
+ <TableCell className="text-right font-bold text-lg">
+ {new Intl.NumberFormat('ko-KR', {
+ style: 'currency',
+ currency: 'KRW'
+ }).format(totalAmount)}
+ </TableCell>
+ <TableCell></TableCell>
+ </TableRow>
+ </TableFooter>
+ </Table>
+ )}
+ </div>
+ </DialogContent>
+ </Dialog>
+ );
+} \ No newline at end of file