"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";
// 인터페이스
interface Attachment {
id: number;
fileName: string;
filePath: string;
fileType?: string;
}
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 (
<>
{open && (
)}
>
);
}
const DocumentViewer: React.FC<{
open: boolean;
setOpen: React.Dispatch>;
versions: Version[];
}> = ({ open, setOpen, versions }) => {
const [instance, setInstance] = React.useState(
null
);
const [viwerLoading, setViewerLoading] = React.useState(true);
const [fileSetLoading, setFileSetLoading] = React.useState(true);
const viewer = React.useRef(null);
const initialized = React.useRef(false);
const isCancelled = React.useRef(false); // 초기화 중단용 flag
const cleanupHtmlStyle = () => {
const htmlElement = document.documentElement;
// 기존 style 속성 가져오기
const originalStyle = htmlElement.getAttribute("style") || "";
// "color-scheme: light" 또는 "color-scheme: dark" 찾기
const colorSchemeStyle = originalStyle
.split(";")
.map((s) => s.trim())
.find((s) => s.startsWith("color-scheme:"));
// 새로운 스타일 적용 (color-scheme만 유지)
if (colorSchemeStyle) {
htmlElement.setAttribute("style", colorSchemeStyle + ";");
} else {
htmlElement.removeAttribute("style"); // color-scheme도 없으면 style 속성 자체 삭제
}
console.log("html style 삭제");
};
React.useEffect(() => {
if (open && !initialized.current) {
initialized.current = true;
isCancelled.current = false; // 다시 열릴 때는 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);
});
});
}
});
}
return () => {
// cleanup 시에는 중단 flag 세움
if (instance) {
instance.UI.dispose();
}
setTimeout(() => cleanupHtmlStyle(), 500);
};
}, [open]);
React.useEffect(() => {
const loadDocument = async () => {
if (instance && versions.length > 0) {
const { UI } = instance;
const optionsArray: any[] = [];
versions.forEach((c) => {
const { attachments } = c;
attachments.forEach((c2) => {
const { fileName, filePath, fileType } = c2;
const fileTypeCur = fileType ?? "";
const options = {
filename: fileName,
...(fileTypeCur.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 (
);
};