diff --git a/frontend/components/report/designer/ReportPreviewModal.tsx b/frontend/components/report/designer/ReportPreviewModal.tsx index 8f39cc4f..f058e513 100644 --- a/frontend/components/report/designer/ReportPreviewModal.tsx +++ b/frontend/components/report/designer/ReportPreviewModal.tsx @@ -42,85 +42,215 @@ export function ReportPreviewModal({ isOpen, onClose }: ReportPreviewModalProps) }; const handlePrint = () => { - // 현재 미리보기 영역만 인쇄 - const printContent = document.getElementById("preview-content"); - if (!printContent) return; + // HTML 생성하여 인쇄 + const printHtml = generatePrintHTML(); const printWindow = window.open("", "_blank"); if (!printWindow) return; - printWindow.document.write(` - - - 리포트 인쇄 - - - - ${printContent.innerHTML} - - - `); + printWindow.document.write(printHtml); printWindow.document.close(); printWindow.print(); }; - // PDF 다운로드 (브라우저 인쇄 기능 이용) - const handleDownloadPDF = () => { - const printContent = document.getElementById("preview-content"); - if (!printContent) return; + // HTML 생성 (인쇄/PDF용) + const generatePrintHTML = (): string => { + // 컴포넌트별 HTML 생성 + const componentsHTML = components + .map((component) => { + const queryResult = component.queryId ? getQueryResult(component.queryId) : null; + let content = ""; - const printWindow = window.open("", "_blank"); - if (!printWindow) return; + // Text/Label 컴포넌트 + if (component.type === "text" || component.type === "label") { + const displayValue = getComponentValue(component); + content = `
${displayValue}
`; + } - printWindow.document.write(` + // Image 컴포넌트 + else if (component.type === "image" && component.imageUrl) { + const imageUrl = component.imageUrl.startsWith("data:") + ? component.imageUrl + : getFullImageUrl(component.imageUrl); + content = ``; + } + + // Divider 컴포넌트 + else if (component.type === "divider") { + const width = component.orientation === "horizontal" ? "100%" : `${component.lineWidth || 1}px`; + const height = component.orientation === "vertical" ? "100%" : `${component.lineWidth || 1}px`; + content = `
`; + } + + // Signature 컴포넌트 + else if (component.type === "signature") { + const labelPosition = component.labelPosition || "left"; + const showLabel = component.showLabel !== false; + const labelText = component.labelText || "서명:"; + const imageUrl = component.imageUrl + ? component.imageUrl.startsWith("data:") + ? component.imageUrl + : getFullImageUrl(component.imageUrl) + : ""; + + if (labelPosition === "left" || labelPosition === "right") { + content = ` +
+ ${showLabel ? `
${labelText}
` : ""} +
+ ${imageUrl ? `` : ""} + ${component.showUnderline ? '
' : ""} +
+
`; + } else { + content = ` +
+ ${showLabel && labelPosition === "top" ? `
${labelText}
` : ""} +
+ ${imageUrl ? `` : ""} + ${component.showUnderline ? '
' : ""} +
+ ${showLabel && labelPosition === "bottom" ? `
${labelText}
` : ""} +
`; + } + } + + // Stamp 컴포넌트 + else if (component.type === "stamp") { + const showLabel = component.showLabel !== false; + const labelText = component.labelText || "(인)"; + const personName = component.personName || ""; + const imageUrl = component.imageUrl + ? component.imageUrl.startsWith("data:") + ? component.imageUrl + : getFullImageUrl(component.imageUrl) + : ""; + + content = ` +
+ ${personName ? `
${personName}
` : ""} +
+ ${imageUrl ? `` : ""} + ${showLabel ? `
${labelText}
` : ""} +
+
`; + } + + // Table 컴포넌트 + else if (component.type === "table" && queryResult && queryResult.rows.length > 0) { + const columns = + component.tableColumns && component.tableColumns.length > 0 + ? component.tableColumns + : queryResult.fields.map((field) => ({ + field, + header: field, + align: "left" as const, + width: undefined, + })); + + const tableRows = queryResult.rows + .map( + (row) => ` + + ${columns.map((col) => `${String(row[col.field] ?? "")}`).join("")} + + `, + ) + .join(""); + + content = ` + + + + ${columns.map((col) => ``).join("")} + + + + ${tableRows} + +
${col.header}
`; + } + + return ` +
+ ${content} +
`; + }) + .join(""); + + return ` + 리포트 인쇄 - ${printContent.innerHTML} + - - `); + `; + }; + + // PDF 다운로드 (브라우저 인쇄 기능 이용) + const handleDownloadPDF = () => { + const printHtml = generatePrintHTML(); + + const printWindow = window.open("", "_blank"); + if (!printWindow) return; + + printWindow.document.write(printHtml); printWindow.document.close(); toast({ @@ -306,6 +436,7 @@ export function ReportPreviewModal({ isOpen, onClose }: ReportPreviewModalProps) field, header: field, align: "left" as const, + width: undefined, })); return (