summaryrefslogtreecommitdiff
path: root/lib/po/vendor-table/vendor-po-note-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/po/vendor-table/vendor-po-note-dialog.tsx')
-rw-r--r--lib/po/vendor-table/vendor-po-note-dialog.tsx162
1 files changed, 162 insertions, 0 deletions
diff --git a/lib/po/vendor-table/vendor-po-note-dialog.tsx b/lib/po/vendor-table/vendor-po-note-dialog.tsx
new file mode 100644
index 00000000..fbc14563
--- /dev/null
+++ b/lib/po/vendor-table/vendor-po-note-dialog.tsx
@@ -0,0 +1,162 @@
+"use client"
+
+import * as React from "react"
+import {
+ Dialog,
+ DialogContent,
+ DialogDescription,
+ DialogHeader,
+ DialogTitle,
+} from "@/components/ui/dialog"
+import { Badge } from "@/components/ui/badge"
+import { Separator } from "@/components/ui/separator"
+import { ScrollArea } from "@/components/ui/scroll-area"
+import { FileTextIcon, MessageSquareIcon } from "lucide-react"
+import { VendorPO } from "./types"
+
+interface VendorPONoteDialogProps {
+ open: boolean
+ onOpenChange: (open: boolean) => void
+ po: VendorPO | null
+}
+
+interface PONoteItem {
+ itemNo: string
+ description: string
+ remark: string
+}
+
+export function VendorPONoteDialog({
+ open,
+ onOpenChange,
+ po,
+}: VendorPONoteDialogProps) {
+ // 계약서 내용 및 노트 데이터를 추출하는 함수
+ const extractContent = React.useCallback(() => {
+ if (!po) return { contractContent: null, remarks: null, itemNotes: [] }
+
+ const contractContent = po.contractContent || null // contracts.contractContent (ZMM_NOTE에서 추출)
+ const remarks = po.remarks || null // contracts.remarks (추가 비고)
+ const itemNotes: PONoteItem[] = []
+
+ // items 배열에서 remark이 있는 항목들 추출
+ if (po.items && po.items.length > 0) {
+ po.items.forEach((item, index) => {
+ if (item.remark && item.remark.trim()) {
+ itemNotes.push({
+ itemNo: item.itemNo || `Item ${index + 1}`,
+ description: item.itemDescription || item.materialSpec || '',
+ remark: item.remark,
+ })
+ }
+ })
+ }
+
+ return { contractContent, remarks, itemNotes }
+ }, [po])
+
+ const { contractContent, remarks, itemNotes } = extractContent()
+ const hasAnyContent = contractContent || remarks || itemNotes.length > 0
+
+ return (
+ <Dialog open={open} onOpenChange={onOpenChange}>
+ <DialogContent className="sm:max-w-[600px] max-h-[80vh]">
+ <DialogHeader>
+ <DialogTitle className="flex items-center gap-2">
+ <FileTextIcon className="h-5 w-5" />
+ 계약서 내용 - {po?.contractNo}
+ </DialogTitle>
+ <DialogDescription>
+ {po?.contractName} 계약의 계약서 내용 및 관련 노트입니다.
+ </DialogDescription>
+ </DialogHeader>
+
+ <ScrollArea className="max-h-[60vh] pr-4">
+ <div className="space-y-6">
+ {/* 계약서 내용 (메인) */}
+ {contractContent && (
+ <div className="space-y-3">
+ <div className="flex items-center gap-2">
+ <FileTextIcon className="h-4 w-4 text-blue-600" />
+ <h3 className="text-sm font-semibold text-blue-600">
+ 계약서 내용
+ </h3>
+ </div>
+ <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
+ <p className="text-sm text-gray-700 whitespace-pre-wrap leading-relaxed">
+ {contractContent}
+ </p>
+ </div>
+ </div>
+ )}
+
+ {/* 구분선 */}
+ {contractContent && (remarks || itemNotes.length > 0) && <Separator />}
+
+ {/* 계약 비고 */}
+ {remarks && (
+ <div className="space-y-3">
+ <div className="flex items-center gap-2">
+ <MessageSquareIcon className="h-4 w-4 text-orange-600" />
+ <h3 className="text-sm font-semibold text-orange-600">
+ 계약 비고
+ </h3>
+ </div>
+ <div className="bg-orange-50 border border-orange-200 rounded-lg p-4">
+ <p className="text-sm text-gray-700 whitespace-pre-wrap">
+ {remarks}
+ </p>
+ </div>
+ </div>
+ )}
+
+ {/* 구분선 */}
+ {(contractContent || remarks) && itemNotes.length > 0 && <Separator />}
+
+ {/* 아이템별 노트들 */}
+ {itemNotes.length > 0 && (
+ <div className="space-y-4">
+ <div className="flex items-center gap-2">
+ <FileTextIcon className="h-4 w-4 text-green-600" />
+ <h3 className="text-sm font-semibold text-green-600">
+ 품목별 노트 ({itemNotes.length}개)
+ </h3>
+ </div>
+
+ <div className="space-y-3">
+ {itemNotes.map((item, index) => (
+ <div key={index} className="bg-green-50 border border-green-200 rounded-lg p-4">
+ <div className="flex items-start gap-3">
+ <Badge variant="outline" className="text-green-700 border-green-300">
+ {item.itemNo}
+ </Badge>
+ <div className="flex-1 min-w-0">
+ {item.description && (
+ <p className="text-sm font-medium text-gray-900 mb-1 truncate" title={item.description}>
+ {item.description}
+ </p>
+ )}
+ <p className="text-sm text-gray-700 whitespace-pre-wrap">
+ {item.remark}
+ </p>
+ </div>
+ </div>
+ </div>
+ ))}
+ </div>
+ </div>
+ )}
+
+ {/* 내용이 없는 경우 */}
+ {!hasAnyContent && (
+ <div className="text-center py-8">
+ <FileTextIcon className="h-12 w-12 text-gray-400 mx-auto mb-4" />
+ <p className="text-gray-500">등록된 계약서 내용이 없습니다.</p>
+ </div>
+ )}
+ </div>
+ </ScrollArea>
+ </DialogContent>
+ </Dialog>
+ )
+} \ No newline at end of file