From c228a89c2834ee63b209bad608837c39643f350e Mon Sep 17 00:00:00 2001
From: dujinkim <dujin.kim@dtsolution.co.kr>
Date: Mon, 28 Jul 2025 11:44:16 +0000
Subject: (대표님) 의존성 docx 추가, basicContract API, gtc(계약일반조건),
 벤더평가 esg 평가데이터 내보내기 개선, S-EDP 피드백 대응(CLS_ID, ITEM NO 등)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../gtc-clauses/table/preview-document-dialog.tsx  | 189 +++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx

(limited to 'lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx')

diff --git a/lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx b/lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx
new file mode 100644
index 00000000..29ab1b5a
--- /dev/null
+++ b/lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx
@@ -0,0 +1,189 @@
+"use client"
+
+import * as React from "react"
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog"
+import { Button } from "@/components/ui/button"
+import { Badge } from "@/components/ui/badge"
+import { Separator } from "@/components/ui/separator"
+
+import { 
+  Eye, 
+  Download, 
+  Loader2, 
+  FileText, 
+  RefreshCw,
+  Settings 
+} from "lucide-react"
+import { toast } from "sonner"
+
+import { type GtcClauseTreeView } from "@/db/schema/gtc"
+import { ClausePreviewViewer } from "./clause-preview-viewer"
+
+interface PreviewDocumentDialogProps
+  extends React.ComponentPropsWithRef<typeof Dialog> {
+  clauses: GtcClauseTreeView[]
+  document: any
+  onExport?: () => void
+}
+
+export function PreviewDocumentDialog({ 
+  clauses, 
+  document,
+  onExport,
+  ...props 
+}: PreviewDocumentDialogProps) {
+  const [isGenerating, setIsGenerating] = React.useState(false)
+  const [documentGenerated, setDocumentGenerated] = React.useState(false)
+  const [viewerInstance, setViewerInstance] = React.useState<any>(null)
+
+  // 조항 통계 계산
+  const stats = React.useMemo(() => {
+    const activeClausesCount = clauses.filter(c => c.isActive !== false).length
+    const topLevelCount = clauses.filter(c => !c.parentId && c.isActive !== false).length
+    const hasContentCount = clauses.filter(c => c.content && c.isActive !== false).length
+    
+    return {
+      total: activeClausesCount,
+      topLevel: topLevelCount,
+      withContent: hasContentCount,
+      withoutContent: activeClausesCount - hasContentCount
+    }
+  }, [clauses])
+
+  const handleGeneratePreview = async () => {
+    setIsGenerating(true)
+    try {
+      // 잠시 후 문서 생성 완료로 설정 (실제로는 뷰어에서 처리)
+      setTimeout(() => {
+        setDocumentGenerated(true)
+        setIsGenerating(false)
+        toast.success("문서 미리보기가 생성되었습니다.")
+      }, 1500)
+    } catch (error) {
+      setIsGenerating(false)
+      toast.error("문서 생성 중 오류가 발생했습니다.")
+    }
+  }
+
+  const handleExportDocument = () => {
+    if (viewerInstance) {
+      // PDFTron의 다운로드 기능 실행
+      viewerInstance.UI.downloadPdf({
+        filename: `${document?.title || 'GTC계약서'}_미리보기.pdf`
+      })
+      toast.success("문서가 다운로드됩니다.")
+    }
+  }
+
+  const handleRegenerateDocument = () => {
+    setDocumentGenerated(false)
+    handleGeneratePreview()
+  }
+
+  React.useEffect(() => {
+    // 다이얼로그가 열릴 때 자동으로 미리보기 생성
+    if (props.open && !documentGenerated && !isGenerating) {
+      handleGeneratePreview()
+    }
+  }, [props.open])
+
+  return (
+    <Dialog {...props}>
+      <DialogContent className="max-w-7xl h-[90vh] flex flex-col">
+        <DialogHeader className="flex-shrink-0">
+          <DialogTitle className="flex items-center gap-2">
+            <Eye className="h-5 w-5" />
+            문서 미리보기
+          </DialogTitle>
+          <DialogDescription>
+            현재 조항들을 기반으로 생성된 문서를 미리보기합니다.
+          </DialogDescription>
+        </DialogHeader>
+
+        {/* 문서 정보 및 통계 */}
+        <div className="flex-shrink-0 p-4 bg-muted/30 rounded-lg">
+          <div className="flex items-center justify-between mb-3">
+            <div className="flex items-center gap-2">
+              <FileText className="h-4 w-4" />
+              <span className="font-medium">{document?.title || 'GTC 계약서'}</span>
+              <Badge variant="outline">{stats.total}개 조항</Badge>
+            </div>
+            <div className="flex items-center gap-2">
+              {documentGenerated && (
+                <>
+                  <Button
+                    variant="outline"
+                    size="sm"
+                    onClick={handleRegenerateDocument}
+                    disabled={isGenerating}
+                  >
+                    <RefreshCw className="mr-2 h-3 w-3" />
+                    재생성
+                  </Button>
+                  <Button
+                    variant="outline"
+                    size="sm"
+                    onClick={handleExportDocument}
+                  >
+                    <Download className="mr-2 h-3 w-3" />
+                    PDF 다운로드
+                  </Button>
+                </>
+              )}
+            </div>
+          </div>
+
+          <div className="grid grid-cols-4 gap-4 text-sm">
+            <div className="text-center p-2 bg-background rounded">
+              <div className="font-medium text-lg">{stats.total}</div>
+              <div className="text-muted-foreground">총 조항</div>
+            </div>
+            <div className="text-center p-2 bg-background rounded">
+              <div className="font-medium text-lg">{stats.topLevel}</div>
+              <div className="text-muted-foreground">최상위 조항</div>
+            </div>
+            <div className="text-center p-2 bg-background rounded">
+              <div className="font-medium text-lg text-green-600">{stats.withContent}</div>
+              <div className="text-muted-foreground">내용 있음</div>
+            </div>
+            <div className="text-center p-2 bg-background rounded">
+              <div className="font-medium text-lg text-amber-600">{stats.withoutContent}</div>
+              <div className="text-muted-foreground">제목만</div>
+            </div>
+          </div>
+        </div>
+
+        <Separator />
+
+        {/* PDFTron 뷰어 영역 */}
+        <div className="flex-1 min-h-0 relative">
+          {isGenerating ? (
+            <div className="absolute inset-0 flex flex-col items-center justify-center bg-background">
+              <Loader2 className="h-8 w-8 animate-spin text-primary mb-4" />
+              <p className="text-lg font-medium mb-2">문서 생성 중...</p>
+              <p className="text-sm text-muted-foreground">
+                {stats.total}개의 조항을 배치하고 있습니다.
+              </p>
+            </div>
+          ) : documentGenerated ? (
+            <ClausePreviewViewer
+              clauses={clauses}
+              document={document}
+              instance={viewerInstance}
+              setInstance={setViewerInstance}
+            />
+          ) : (
+            <div className="absolute inset-0 flex flex-col items-center justify-center bg-muted/10">
+              <FileText className="h-12 w-12 text-muted-foreground mb-4" />
+              <p className="text-lg font-medium mb-2">문서 미리보기 준비 중</p>
+              <Button onClick={handleGeneratePreview} disabled={isGenerating}>
+                <Eye className="mr-2 h-4 w-4" />
+                미리보기 생성
+              </Button>
+            </div>
+          )}
+        </div>
+      </DialogContent>
+    </Dialog>
+  )
+}
\ No newline at end of file
-- 
cgit v1.2.3

