summaryrefslogtreecommitdiff
path: root/lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx')
-rw-r--r--lib/gtc-contract/gtc-clauses/table/preview-document-dialog.tsx189
1 files changed, 189 insertions, 0 deletions
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