summaryrefslogtreecommitdiff
path: root/components/documents
diff options
context:
space:
mode:
Diffstat (limited to 'components/documents')
-rw-r--r--components/documents/view-document-dialog.tsx213
1 files changed, 213 insertions, 0 deletions
diff --git a/components/documents/view-document-dialog.tsx b/components/documents/view-document-dialog.tsx
index eaa09fad..7603fdc0 100644
--- a/components/documents/view-document-dialog.tsx
+++ b/components/documents/view-document-dialog.tsx
@@ -1,3 +1,4 @@
+<<<<<<< HEAD
"use client";
import * as React from "react";
@@ -73,22 +74,95 @@ const DocumentViewer: React.FC<{
);
const [viwerLoading, setViewerLoading] = React.useState<boolean>(true);
const [fileSetLoading, setFileSetLoading] = React.useState<boolean>(true);
+=======
+"use client"
+
+import * as React from "react"
+import { WebViewerInstance } from "@pdftron/webviewer";
+import {
+ Dialog, DialogTrigger, DialogContent, DialogHeader,
+ DialogTitle, DialogDescription, DialogFooter
+} from "@/components/ui/dialog"
+import { Building2, FileIcon, Loader2 } from "lucide-react"
+import { Button } from "@/components/ui/button"
+import fs from "fs"
+
+interface Version {
+ id: number
+ stage: string
+ revision: string
+ uploaderType: string
+ uploaderName: string | null
+ comment: string | null
+ status: string | null
+ planDate: string | null
+ actualDate: string | null
+ approvedDate: string | null
+ DocumentSubmitDate: Date
+ attachments: Attachment[]
+ selected: boolean
+}
+
+type ViewDocumentDialogProps = {
+ versions: Version[]
+}
+
+export function ViewDocumentDialog({versions}: ViewDocumentDialogProps){
+ const [open, setOpen] = React.useState(false)
+
+
+ return (
+ <>
+ <Button
+ size="sm"
+ className="border-blue-200"
+ variant="outline"
+ onClick={() => setOpen(prev => !prev)}
+ >
+ 문서 보기
+ </Button>
+ {open && <DocumentViewer
+ open={open}
+ setOpen={setOpen}
+ versions={versions}
+ />
+ }
+ </>
+ );
+}
+
+function DocumentViewer({open, setOpen, versions}){
+ const [instance, setInstance] = React.useState<null | WebViewerInstance>(null)
+ const [viwerLoading, setViewerLoading] = React.useState<boolean>(true)
+ const [fileSetLoading, setFileSetLoading] = React.useState<boolean>(true)
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
const viewer = React.useRef<HTMLDivElement>(null);
const initialized = React.useRef(false);
const isCancelled = React.useRef(false); // 초기화 중단용 flag
const cleanupHtmlStyle = () => {
const htmlElement = document.documentElement;
+<<<<<<< HEAD
// 기존 style 속성 가져오기
const originalStyle = htmlElement.getAttribute("style") || "";
+=======
+
+ // 기존 style 속성 가져오기
+ const originalStyle = htmlElement.getAttribute("style") || "";
+
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
// "color-scheme: light" 또는 "color-scheme: dark" 찾기
const colorSchemeStyle = originalStyle
.split(";")
.map((s) => s.trim())
.find((s) => s.startsWith("color-scheme:"));
+<<<<<<< HEAD
+=======
+
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
// 새로운 스타일 적용 (color-scheme만 유지)
if (colorSchemeStyle) {
htmlElement.setAttribute("style", colorSchemeStyle + ";");
@@ -96,13 +170,18 @@ const DocumentViewer: React.FC<{
htmlElement.removeAttribute("style"); // color-scheme도 없으면 style 속성 자체 삭제
}
+<<<<<<< HEAD
console.log("html style 삭제");
+=======
+ console.log("html style 삭제")
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
};
React.useEffect(() => {
if (open && !initialized.current) {
initialized.current = true;
isCancelled.current = false; // 다시 열릴 때는 false로 리셋
+<<<<<<< HEAD
requestAnimationFrame(() => {
if (viewer.current) {
@@ -130,11 +209,41 @@ const DocumentViewer: React.FC<{
"multiTabsEmptyPage",
]);
setViewerLoading(false);
+=======
+
+ requestAnimationFrame(() => {
+ if (viewer.current) {
+ import("@pdftron/webviewer").then(({ default: WebViewer }) => {
+ console.log(isCancelled.current)
+ if (isCancelled.current) {
+ console.log("📛 WebViewer 초기화 취소됨 (Dialog 닫힘)");
+
+ return;
+ }
+
+ WebViewer(
+ {
+ path: "/pdftronWeb",
+ licenseKey: "demo:1739264618684:616161d7030000000091db1c97c6f386d41d3506ab5b507381ef2ee2bd",
+ fullAPI: true,
+ css:"/globals.css"
+ },
+ viewer.current as HTMLDivElement
+ ).then(async (instance: WebViewerInstance) => {
+
+
+ setInstance(instance);
+ instance.UI.enableFeatures([instance.UI.Feature.MultiTab]);
+ instance.UI.disableElements(["addTabButton", "multiTabsEmptyPage"]);
+ setViewerLoading(false);
+
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
});
});
}
});
}
+<<<<<<< HEAD
return () => {
// cleanup 시에는 중단 flag 세움
@@ -142,10 +251,20 @@ const DocumentViewer: React.FC<{
instance.UI.dispose();
}
setTimeout(() => cleanupHtmlStyle(), 500);
+=======
+
+ return async () => {
+ // cleanup 시에는 중단 flag 세움
+ if(instance){
+ await instance.UI.dispose()
+ }
+ await setTimeout(() => cleanupHtmlStyle(), 500)
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
};
}, [open]);
React.useEffect(() => {
+<<<<<<< HEAD
const loadDocument = async () => {
if (instance && versions.length > 0) {
const { UI } = instance;
@@ -211,10 +330,77 @@ const DocumentViewer: React.FC<{
try {
await instance.UI.dispose();
setInstance(null); // 상태도 초기화
+=======
+ const loadDocument = async () => {
+
+ if(instance && versions.length > 0){
+ const { UI } = instance;
+
+ const optionsArray = []
+
+ versions.forEach(c => {
+ const {attachments} = c
+ attachments.forEach(c2 => {
+ const {fileName, filePath, fileType} = c2
+
+ const options = {
+ filename: fileName,
+ ...(fileType.includes("xlsx") && {
+ officeOptions: {
+ formatOptions: {
+ applyPageBreaksToSheet: true,
+ },
+ },
+ }),
+ };
+
+ optionsArray.push({
+ filePath,
+ options
+ })
+ })
+ })
+
+ const tabIds = [];
+
+ for (const option of optionsArray) {
+ const { filePath, options } = option;
+ const response = await fetch(filePath);
+ const blob = await response.blob();
+
+ const tab = await UI.TabManager.addTab(blob, options);
+ tabIds.push(tab); // 탭 ID 저장
+ }
+
+ if (tabIds.length > 0) {
+ await UI.TabManager.setActiveTab(tabIds[0]);
+ }
+
+ setFileSetLoading(false)
+ }
+ }
+ loadDocument();
+ }, [instance, versions])
+
+
+ return (
+ <Dialog open={open} onOpenChange={async (val) => {
+ console.log({val, fileSetLoading})
+ if(!val && fileSetLoading){
+ return;
+ }
+
+ if (instance) {
+ try {
+ await instance.UI.dispose();
+ setInstance(null); // 상태도 초기화
+
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d
} catch (e) {
console.warn("dispose error", e);
}
}
+<<<<<<< HEAD
// cleanupHtmlStyle()
setViewerLoading(false);
@@ -244,3 +430,30 @@ const DocumentViewer: React.FC<{
</Dialog>
);
};
+=======
+
+ // cleanupHtmlStyle()
+ setViewerLoading(false);
+ setOpen(prev => !prev)
+ await setTimeout(() => cleanupHtmlStyle(), 1000)
+ }}>
+ <DialogContent className="w-[90vw] h-[90vh]" style={{maxWidth: "none"}}>
+ <DialogHeader className="h-[38px]">
+ <DialogTitle>
+ 문서 미리보기
+ </DialogTitle>
+ <DialogDescription>
+ 첨부파일 미리보기
+ </DialogDescription>
+ </DialogHeader>
+ <div ref={viewer} style={{height: "calc(90vh - 20px - 38px - 1rem - 48px)"}}>
+ {viwerLoading && <div className="flex flex-col items-center justify-center py-12">
+ <Loader2 className="h-8 w-8 text-blue-500 animate-spin mb-4" />
+ <p className="text-sm text-muted-foreground">문서 뷰어 로딩 중...</p>
+ </div>}
+ </div>
+ </DialogContent>
+ </Dialog>
+ );
+}
+>>>>>>> cac978d5c77e9b30165e4fbe6930eeac9862204d