미리보기 기능 구현
This commit is contained in:
parent
579d4224d5
commit
7a588b47f6
|
|
@ -18,10 +18,49 @@ interface ReportPreviewModalProps {
|
|||
}
|
||||
|
||||
export function ReportPreviewModal({ isOpen, onClose }: ReportPreviewModalProps) {
|
||||
const { components, canvasWidth, canvasHeight } = useReportDesigner();
|
||||
const { components, canvasWidth, canvasHeight, getQueryResult } = useReportDesigner();
|
||||
|
||||
// 컴포넌트의 실제 표시 값 가져오기
|
||||
const getComponentValue = (component: any): string => {
|
||||
if (component.queryId && component.fieldName) {
|
||||
const queryResult = getQueryResult(component.queryId);
|
||||
if (queryResult && queryResult.rows.length > 0) {
|
||||
const value = queryResult.rows[0][component.fieldName];
|
||||
if (value !== null && value !== undefined) {
|
||||
return String(value);
|
||||
}
|
||||
}
|
||||
return `{${component.fieldName}}`;
|
||||
}
|
||||
return component.defaultValue || "텍스트";
|
||||
};
|
||||
|
||||
const handlePrint = () => {
|
||||
window.print();
|
||||
// 현재 미리보기 영역만 인쇄
|
||||
const printContent = document.getElementById("preview-content");
|
||||
if (!printContent) return;
|
||||
|
||||
const printWindow = window.open("", "_blank");
|
||||
if (!printWindow) return;
|
||||
|
||||
printWindow.document.write(`
|
||||
<html>
|
||||
<head>
|
||||
<title>리포트 인쇄</title>
|
||||
<style>
|
||||
body { margin: 0; padding: 20px; }
|
||||
@media print {
|
||||
body { margin: 0; padding: 0; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${printContent.innerHTML}
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
printWindow.document.close();
|
||||
printWindow.print();
|
||||
};
|
||||
|
||||
const handleDownloadPDF = () => {
|
||||
|
|
@ -45,63 +84,82 @@ export function ReportPreviewModal({ isOpen, onClose }: ReportPreviewModalProps)
|
|||
{/* 미리보기 영역 */}
|
||||
<div className="max-h-[500px] overflow-auto rounded border bg-gray-100 p-4">
|
||||
<div
|
||||
id="preview-content"
|
||||
className="relative mx-auto bg-white shadow-lg"
|
||||
style={{
|
||||
width: `${canvasWidth}mm`,
|
||||
minHeight: `${canvasHeight}mm`,
|
||||
}}
|
||||
>
|
||||
{components.map((component) => (
|
||||
<div
|
||||
key={component.id}
|
||||
className="absolute rounded border bg-white p-2"
|
||||
style={{
|
||||
left: `${component.x}px`,
|
||||
top: `${component.y}px`,
|
||||
width: `${component.width}px`,
|
||||
height: `${component.height}px`,
|
||||
fontSize: `${component.fontSize}px`,
|
||||
color: component.fontColor,
|
||||
backgroundColor: component.backgroundColor,
|
||||
borderColor: component.borderColor,
|
||||
borderWidth: `${component.borderWidth}px`,
|
||||
}}
|
||||
>
|
||||
{component.type === "text" && (
|
||||
<div>
|
||||
<div className="mb-1 text-xs text-gray-500">텍스트 필드</div>
|
||||
<div>샘플 텍스트</div>
|
||||
</div>
|
||||
)}
|
||||
{component.type === "label" && (
|
||||
<div>
|
||||
<div className="mb-1 text-xs text-gray-500">레이블</div>
|
||||
<div className="font-semibold">레이블 텍스트</div>
|
||||
</div>
|
||||
)}
|
||||
{component.type === "table" && (
|
||||
<div className="overflow-auto">
|
||||
<div className="mb-1 text-xs text-gray-500">테이블</div>
|
||||
{components.map((component) => {
|
||||
const displayValue = getComponentValue(component);
|
||||
const queryResult = component.queryId ? getQueryResult(component.queryId) : null;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={component.id}
|
||||
className="absolute"
|
||||
style={{
|
||||
left: `${component.x}px`,
|
||||
top: `${component.y}px`,
|
||||
width: `${component.width}px`,
|
||||
height: `${component.height}px`,
|
||||
}}
|
||||
>
|
||||
{component.type === "text" && (
|
||||
<div
|
||||
style={{
|
||||
fontSize: `${component.fontSize}px`,
|
||||
color: component.fontColor,
|
||||
backgroundColor: component.backgroundColor,
|
||||
}}
|
||||
>
|
||||
{displayValue}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{component.type === "label" && (
|
||||
<div
|
||||
className="font-semibold"
|
||||
style={{
|
||||
fontSize: `${component.fontSize}px`,
|
||||
color: component.fontColor,
|
||||
backgroundColor: component.backgroundColor,
|
||||
}}
|
||||
>
|
||||
{displayValue}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{component.type === "table" && queryResult && queryResult.rows.length > 0 ? (
|
||||
<table className="w-full border-collapse text-xs">
|
||||
<thead>
|
||||
<tr className="bg-gray-100">
|
||||
<th className="border p-1">품목명</th>
|
||||
<th className="border p-1">수량</th>
|
||||
<th className="border p-1">단가</th>
|
||||
{queryResult.fields.map((field) => (
|
||||
<th key={field} className="border border-gray-300 p-1">
|
||||
{field}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="border p-1">샘플1</td>
|
||||
<td className="border p-1">10</td>
|
||||
<td className="border p-1">50,000</td>
|
||||
</tr>
|
||||
{queryResult.rows.map((row, idx) => (
|
||||
<tr key={idx}>
|
||||
{queryResult.fields.map((field) => (
|
||||
<td key={field} className="border border-gray-300 p-1">
|
||||
{String(row[field] ?? "")}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
) : component.type === "table" ? (
|
||||
<div className="text-xs text-gray-400">쿼리를 실행해주세요</div>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue