diff options
Diffstat (limited to 'lib/po/vendor-table/vendor-po-note-dialog.tsx')
| -rw-r--r-- | lib/po/vendor-table/vendor-po-note-dialog.tsx | 162 |
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 |
